Compare commits

..

3 Commits

Author SHA1 Message Date
d133cb0916 update .gitignore 2006-06-22 21:31:49 +02:00
05c682ad94 test 2006-06-22 21:26:55 +02:00
05c199f20a first try 2006-06-22 21:16:02 +02:00
61 changed files with 1203 additions and 5896 deletions

28
.gitignore vendored
View File

@ -2,6 +2,30 @@
*.so
*.d
sammler
sammler_norrd
sammler.log
rrd
Makefile.in
aclocal.m4
autoconfig.h.in
autom4te.cache
config.guess
config.sub
configure
install-sh
ltmain.sh
missing
Makefile
autoconfig.h
config.log
config.status
libtool
stamp-h1
.libs
autoconfig.h.in~
*.la
*.lo
sammler-*.tar.bz2
sammler-*.tar.gz

0
ChangeLog Normal file
View File

236
INSTALL Normal file
View File

@ -0,0 +1,236 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script). Here is a another example:
/bin/bash ./configure CONFIG_SHELL=/bin/bash
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
configuration-related scripts to be executed by `/bin/bash'.
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

110
Makefile
View File

@ -1,110 +0,0 @@
# Toplevel Makefile
WITH_RRD?=yes
PLUGINS := ctstat diskstat hwmon load memory mount netdev random rtstat stat uptime vmstat
#PLUGINS += apache mysql conntrack alixusv ts2 diskstandby hddtemp
DESTDIR =
BINARY_DIR = /usr/local/bin
CONFIG_DIR = /usr/local/etc
PLUGIN_DIR = /usr/local/lib/sammler
DATA_DIR = /var/lib/sammler
LOG_DIR = /var/log
PID_DIR = /var/run
WWW_DIR = /var/www
WWW_CONFIG = $(WWW_DIR)/sammler_graph.conf
WWW_OWNER = www-data
# ############################
SRC := $(wildcard *.c)
BUILD_DIR = build
CFLAGS = -O2 -g -pipe -Wall -Wno-unused-result -I.
CFLAGS += -MMD -MF $(BUILD_DIR)/$(*D)/$(*F).d
LDFLAGS = -rdynamic -ldl
# ############################
ifeq ("$(WITH_RRD)", "yes")
CFLAGS += -DWITH_RRD
LDFLAGS_TARGET = -lrrd
TARGET = sammler
else
LDFLAGS_TARGET =
TARGET = sammler_norrd
endif
ifeq ($(strip $(wildcard $(DESTDIR)$(CONFIG_DIR)/sammler.conf)),)
NEWCONF=sammler.conf
else
NEWCONF=sammler.conf.dist
endif
# ############################
all: $(TARGET) plugins
$(TARGET): $(patsubst %,$(BUILD_DIR)/%, $(SRC:.c=.o))
@echo " Linking file: $@"
@$(CC) $^ $(LDFLAGS) $(LDFLAGS_TARGET) -o $@
$(BUILD_DIR)/%.o: %.c $(MAKEFILE_LIST)
@echo " Building file: $<"
@$(shell test -d $(BUILD_DIR)/$(*D) || mkdir -p $(BUILD_DIR)/$(*D))
@$(CC) $(CFLAGS) -o $@ -c $<
.PHONY: plugins
plugins: $(PLUGINS:%=plugins/%.so)
.SECONDARY: $(patsubst %,$(BUILD_DIR)/%, $(PLUGINS:%=plugins/%.o))
plugins/%.so: $(BUILD_DIR)/plugins/%.o
@echo " Linking file: $@"
@$(CC) $(LDFLAGS) -shared -o $@ $<
plugins/apache.so: $(BUILD_DIR)/plugins/apache.o
@echo " Linking file: $@"
@$(CC) $(LDFLAGS) -shared -lcurl -o $@ $<
plugins/conntrack.so: $(BUILD_DIR)/plugins/conntrack.o
@echo " Linking file: $@"
@$(CC) $(LDFLAGS) -shared -lnfnetlink -lnetfilter_conntrack -o $@ $<
plugins/mysql.so: $(BUILD_DIR)/plugins/mysql.o $(BUILD_DIR)/plugins/mysql_helper.o
@echo " Linking file: $@"
@$(CC) $(LDFLAGS) -shared -lmysqlclient -o $@ $^
plugins/diskstandby.so: $(BUILD_DIR)/plugins/diskstandby.o $(BUILD_DIR)/plugins/sgio.o
@echo " Linking file: $@"
@$(CC) $(LDFLAGS) -shared -o $@ $^
install: all
install -D -m 755 -s $(TARGET) $(DESTDIR)$(BINARY_DIR)/$(TARGET)
install -D -m 644 sammler.conf $(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
sed -i -e "s:^logfile .*$$:logfile $(LOG_DIR)/sammler.log:" \
-e "s:^pidfile .*$$:pidfile $(PID_DIR)/sammler.pid:" \
-e "s:^rrd_dir .*$$:rrd_dir $(DATA_DIR):" \
-e "s:^plugin_dir .*$$:plugin_dir $(PLUGIN_DIR):" \
$(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
install -d -m 755 $(DESTDIR)$(PLUGIN_DIR)
install -m 755 -s plugins/*.so $(DESTDIR)$(PLUGIN_DIR)
install -d -m 755 $(DESTDIR)$(LOG_DIR)
ifeq ("$(WITH_RRD)", "yes")
install -d -m 755 $(DESTDIR)$(DATA_DIR)
install -D -m 644 sammler.php $(DESTDIR)$(WWW_DIR)/sammler.php
sed -i -e "s:%%WWW_CONFIG%%:$(WWW_CONFIG):" \
-e "s:%%DATA_DIR%%:$(DATA_DIR)/:" \
$(DESTDIR)$(WWW_DIR)/sammler.php
ifeq ($(strip $(wildcard $(DESTDIR)$(WWW_CONFIG))),)
-install -D -m 644 -o $(WWW_OWNER) /dev/null $(DESTDIR)$(WWW_CONFIG)
endif
else
sed -i -e "s:^forward_only .*$$:forward_only true:" \
$(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
endif
clean:
rm -rf build plugins/*.so $(TARGET)
include $(shell find $(BUILD_DIR) -name \*.d 2> /dev/null)

59
Makefile.am Normal file
View File

@ -0,0 +1,59 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = sammler.conf
AM_CFLAGS = -Wall -Werror
bin_PROGRAMS = sammler
sammler_SOURCES = config.c config.h \
list.h \
logging.c logging.h \
plugins.c plugins.h \
rrdtool.c rrdtool.h \
sammler.c
sammler_LDADD = -ldl -lrrd
sammler_LDFLAGS = -rdynamic
pkglib_LTLIBRARIES =
pkglib_LTLIBRARIES += p_ctstat.la
p_ctstat_la_SOURCES = p_ctstat.c
p_ctstat_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_load.la
p_load_la_SOURCES = p_load.c
p_load_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_memory.la
p_memory_la_SOURCES = p_memory.c
p_memory_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_mount.la
p_mount_la_SOURCES = p_mount.c
p_mount_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_netdev.la
p_netdev_la_SOURCES = p_netdev.c
p_netdev_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_random.la
p_random_la_SOURCES = p_random.c
p_random_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_rtstat.la
p_rtstat_la_SOURCES = p_rtstat.c
p_rtstat_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_stat.la
p_stat_la_SOURCES = p_stat.c
p_stat_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_uptime.la
p_uptime_la_SOURCES = p_uptime.c
p_uptime_la_LDFLAGS = -module -avoid-version
pkglib_LTLIBRARIES += p_vmstat.la
p_vmstat_la_SOURCES = p_vmstat.c
p_vmstat_la_LDFLAGS = -module -avoid-version

0
NEWS Normal file
View File

0
README Normal file
View File

7
autobuild.sh Executable file
View File

@ -0,0 +1,7 @@
#! /bin/sh
autoheader \
&& aclocal \
&& libtoolize --copy --force \
&& automake --add-missing --copy \
&& autoconf

182
config.c Normal file
View File

@ -0,0 +1,182 @@
/***************************************************************************
* Copyright (C) 06/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "list.h"
#include "config.h"
#include "logging.h"
static LIST_HEAD(config_list);
static struct conf_section * config_add_section(char *name)
{
struct conf_section *section;
if (!name)
return NULL;
section = malloc(sizeof(struct conf_section));
if (section) {
INIT_LIST_HEAD(&section->list);
INIT_LIST_HEAD(&section->tupel);
strncpy(section->name, name, sizeof(section->name));
list_add_tail(&section->list, &config_list);
}
return section;
}
static int config_add_tupel(struct conf_section *section, char *option, char *parameter)
{
struct conf_tupel *tupel;
if (!section || !option || !parameter)
return 0;
if (!(tupel = malloc(sizeof(struct conf_tupel))))
return 0;
INIT_LIST_HEAD(&tupel->list);
tupel->option = strdup(option);
tupel->parameter = strdup(parameter);
list_add_tail(&tupel->list, &section->tupel);
return 1;
}
static void config_free(void)
{
struct conf_section *section, *section_tmp;
struct conf_tupel *tupel, *tupel_tmp;
list_for_each_entry_safe(section, section_tmp, &config_list, list) {
list_for_each_entry_safe(tupel, tupel_tmp, &section->tupel, list) {
list_del(&tupel->list);
free(tupel->option);
free(tupel->parameter);
free(tupel);
}
list_del(&section->list);
free(section);
}
}
int config_parse(char *config)
{
struct conf_section *section = NULL;
FILE *fz;
int i = 0, ret = 1;
char *row, *tok, *tok2;
if (!config)
return 0;
if (!(row = malloc(1024)))
return 0;
if (!(fz = fopen(config, "r"))) {
log_print(LOG_ERROR, "config_parse(): %s", config);
return 0;
}
while (fgets(row, 1024, fz)) {
i++;
if (row[0] == '#' || row[0] <= ' ') {
continue;
} else if (row[0] == '[') {
tok = strtok(row +1, " ]\n");
section = config_add_section(tok);
if (!section) {
log_print(LOG_WARN, "config_parse(): invalid section in row %d", i);
ret = 0;
break;
}
continue;
} else if (!section) {
log_print(LOG_WARN, "config_parse(): missing section in row %d", i);
ret = 0;
break;
}
if ((tok = strtok(row, " \n")) && (tok2 = strtok(NULL, " \n")))
if (!config_add_tupel(section, tok, tok2))
log_print(LOG_WARN, "config_parse(): invalid row %d", i);
}
fclose(fz);
free(row);
if (atexit(config_free) != 0) {
log_print(LOG_ERROR, "config_parse(): atexit()");
return 0;
}
return ret;
}
struct conf_section * config_get_section(char *name)
{
struct conf_section *section;
list_for_each_entry(section, &config_list, list) {
if (!strcmp(section->name, name))
return section;
}
return NULL;
}
char * config_get_parameter(struct conf_section *section, char *option)
{
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel, list) {
if (!strcmp(tupel->option, option))
return tupel->parameter;
}
return NULL;
}
char * config_get_string(char *section, char *option, char *def)
{
struct conf_section *tmp;
char *ret;
tmp = config_get_section(section);
if (tmp && (ret = config_get_parameter(tmp, option)))
return ret;
return def;
}
int config_get_int(char *section, char *option, int def)
{
char *ret;
ret = config_get_string(section, option, NULL);
return ret ? atoi(ret) : def;
}

24
config.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "list.h"
struct conf_section {
struct list_head list;
char name[32];
struct list_head tupel;
};
struct conf_tupel {
struct list_head list;
char *option;
char *parameter;
};
int config_parse(char *config);
struct conf_section * config_get_section(char *name);
char * config_get_parameter(struct conf_section *section, char *option);
char * config_get_string(char *section, char *option, char *def);
int config_get_int(char *section, char *option, int def);
#endif /* _CONFIG_H_ */

View File

@ -1,292 +0,0 @@
/***************************************************************************
* Copyright (C) 03/2010 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "configfile.h"
#include "list.h"
#include "logging.h"
#define BUFSIZE 1024
struct conf_section {
struct list_head list;
struct list_head tupel_list;
const char *name;
};
struct conf_tupel {
struct list_head list;
const char *option;
const char *parameter;
};
static LIST_HEAD(config_list);
static struct conf_section * config_add_section(const char *name)
{
struct conf_section *section;
section = malloc(sizeof(struct conf_section) + strlen(name));
if (section == NULL)
return NULL;
INIT_LIST_HEAD(&section->list);
INIT_LIST_HEAD(&section->tupel_list);
section->name = strdup(name);
if (section->name == NULL) {
free(section);
return NULL;
}
list_add_tail(&section->list, &config_list);
return section;
}
static int config_add_tupel(struct conf_section *section, const char *option, const char *parameter)
{
struct conf_tupel *tupel = malloc(sizeof(struct conf_tupel));
if (tupel == NULL)
return -1;
INIT_LIST_HEAD(&tupel->list);
tupel->option = strdup(option);
tupel->parameter = strdup(parameter);
if (tupel->option == NULL || tupel->parameter == NULL) {
free(tupel);
return -1;
}
list_add_tail(&tupel->list, &section->tupel_list);
return 0;
}
int config_parse(const char *config)
{
FILE *fz = fopen(config, "r");
if (fz == NULL) {
log_print(LOG_ERROR, "%s(): failed to open config '%s'", __FUNCTION__, config);
return -1;
}
char *line = malloc(BUFSIZE);
if (line == NULL) {
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
fclose(fz);
return -1;
}
int linenum = 0;
struct conf_section *section = NULL;
while (fgets(line, BUFSIZE, fz) != NULL) {
linenum++;
if (line[0] == '#' || line[0] <= ' ') {
continue;
} else if (line[0] == '[') {
char *tok = strtok(line +1, " ]\n");
if (tok == NULL || (section = config_add_section(tok)) == NULL) {
log_print(LOG_WARN, "%s(): invalid section in row %d", __FUNCTION__, linenum);
free(line);
fclose(fz);
return -1;
}
continue;
} else if (section == NULL) {
log_print(LOG_WARN, "%s(): missing section in row %d", __FUNCTION__, linenum);
free(line);
fclose(fz);
return -1;
}
char *tmp, *tok = strtok_r(line, " \t\n", &tmp);
if (tok != NULL) {
char *tok2;
while ((tok2 = strtok_r(NULL, " \n", &tmp))) {
if (config_add_tupel(section, tok, tok2) != 0)
log_print(LOG_WARN, "%s(): invalid row %d", __FUNCTION__, linenum);
}
}
}
fclose(fz);
free(line);
return 0;
}
void config_free(void)
{
struct conf_section *section, *section_tmp;
struct conf_tupel *tupel, *tupel_tmp;
list_for_each_entry_safe(section, section_tmp, &config_list, list) {
list_for_each_entry_safe(tupel, tupel_tmp, &section->tupel_list, list) {
list_del(&tupel->list);
free((char *)tupel->option);
free((char *)tupel->parameter);
free(tupel);
}
list_del(&section->list);
free(section);
}
}
static struct conf_section * config_get_section(const char *name)
{
struct conf_section *section;
list_for_each_entry(section, &config_list, list) {
if (!strcmp(section->name, name))
return section;
}
return NULL;
}
const char * config_get_string(const char *section_str, const char *option, const char *def)
{
struct conf_section *section = config_get_section(section_str);
if (section != NULL) {
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel_list, list) {
if (!strcmp(tupel->option, option))
return tupel->parameter;
}
}
if (def != NULL)
log_print(LOG_WARN, "config [%s:%s] not found, using default: '%s'",
section_str, option, def);
return def;
}
int config_get_int(const char *section, const char *option, int *value, int def)
{
const char *ret = config_get_string(section, option, NULL);
if (ret == NULL) {
log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'",
section, option, def);
*value = def;
return -1;
}
char *tmp;
*value = strtol(ret, &tmp, 0);
if (*tmp != '\0' && !isspace(*tmp)) {
log_print(LOG_WARN, "config [%s:%s] not an integer: '%s', using default '%d'",
section, option, ret, def);
*value = def;
return -1;
}
return 0;
}
int config_get_strings(const char *section_str, const char *option,
int (*callback)(const char *value, void *privdata),
void *privdata)
{
struct conf_section *section = config_get_section(section_str);
if (section == NULL)
return -1;
int cnt = 0;
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel_list, list) {
if (!strcmp(tupel->option, option))
if (callback(tupel->parameter, privdata) == 0)
cnt++;
}
return cnt;
}
struct strtoken * strtokenize(const char *input, const char *delim, int maxfields)
{
struct strtoken *tokens = malloc(sizeof(struct strtoken) +
(maxfields +1) * sizeof(char *) +
strlen(input));
if (tokens == NULL)
return NULL;
char *ptr = (char *)&tokens->field[maxfields];
strcpy(ptr, input);
tokens->input = input;
tokens->delim = delim;
tokens->maxfields = maxfields;
int i;
char *tmp;
tokens->count = 0;
for (i = 0; i < maxfields; i++) {
tokens->field[i] = strtok_r(ptr, delim, &tmp);
ptr = NULL;
if (tokens->field[i] != NULL)
tokens->count++;
}
return tokens;
}
struct strtoken * config_get_strtoken(const char *section, const char *option, const char *delim, int maxfields)
{
const char *ret = config_get_string(section, option, NULL);
if (ret == NULL) {
log_print(LOG_WARN, "config [%s:%s] not found", section, option);
return NULL;
}
return strtokenize(ret, delim, maxfields);
}
int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields,
int (*callback)(struct strtoken *data, void *privdata),
void *privdata)
{
struct conf_section *section = config_get_section(section_str);
if (section == NULL)
return -1;
int cnt = 0;
struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel_list, list) {
if (!strcmp(tupel->option, option)) {
struct strtoken *tokens = strtokenize(tupel->parameter, delim, maxfields);
if (tokens != NULL) {
if (callback(tokens, privdata) == 0)
cnt++;
free(tokens);
}
}
}
return cnt;
}

View File

@ -1,31 +0,0 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
int config_parse(const char *config);
void config_free(void);
const char * config_get_string(const char *section_str, const char *option, const char *def);
int config_get_int(const char *section, const char *option, int *value, int def);
int config_get_strings(const char *section_str, const char *option,
int (*callback)(const char *value, void *privdata),
void *privdata);
struct strtoken {
const char *input;
const char *delim;
int maxfields;
int count;
char *field[0];
};
struct strtoken * strtokenize(const char *input, const char *delim, int maxfields);
struct strtoken * config_get_strtoken(const char *section_str, const char *option, const char *delim, int maxfields);
int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields,
int (*callback)(struct strtoken *tokens, void *privdata),
void *privdata);
#endif /* _CONFIG_H_ */

21
configure.in Normal file
View File

@ -0,0 +1,21 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(sammler, 0.00)
AC_CONFIG_SRCDIR(sammler.c)
AC_CONFIG_HEADER(autoconfig.h)
AM_INIT_AUTOMAKE(dist-bzip2)
AC_LANG(C)
AC_PREFIX_DEFAULT("/usr/local")
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes")
dnl configure libtool
AC_DISABLE_STATIC
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
AC_OUTPUT(Makefile)

331
event.c
View File

@ -1,331 +0,0 @@
/***************************************************************************
* Copyright (C) 03/2010 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include "list.h"
#include "logging.h"
#include "event.h"
static LIST_HEAD(event_fd_list);
static LIST_HEAD(event_timeout_list);
struct event_fd {
struct list_head list;
unsigned int flags;
int fd;
int (*read_cb)(int fd, void *privdata);
int (*write_cb)(int fd, void *privdata);
void *read_priv;
void *write_priv;
};
struct event_timeout {
struct list_head list;
unsigned int flags;
struct timeval intervall;
struct timeval nextrun;
int (*callback)(int timerid, void *privdata);
int timerid;
void *privdata;
};
struct event_fd * event_add_fd(
struct event_fd *entry,
int fd,
int type,
int (*callback)(int fd, void *privdata),
void *privdata)
{
/* check valid filediskriptor */
if (fd < 0 || fd > FD_SETSIZE) {
log_print(LOG_ERROR, "%s(): invalid fd", __FUNCTION__);
return NULL;
}
/* check valid type (read/write) */
if (!(type & FD_TYPES)) {
log_print(LOG_ERROR, "%s(): invalid type", __FUNCTION__);
return NULL;
}
/* create new entry */
if (entry == NULL) {
entry = malloc(sizeof(struct event_fd));
if (entry == NULL) {
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
return NULL;
}
memset(entry, 0, sizeof(struct event_fd));
entry->flags |= EVENT_NEW;
entry->fd = fd;
/* put it on the list */
list_add_tail(&entry->list, &event_fd_list);
}
if (type & FD_READ) {
entry->flags = (callback != NULL) ? (entry->flags | FD_READ | EVENT_NEW) : (entry->flags & ~FD_READ);
entry->read_cb = callback;
entry->read_priv = privdata;
} else if (type & FD_WRITE) {
entry->flags = (callback != NULL) ? (entry->flags | FD_WRITE | EVENT_NEW) : (entry->flags & ~FD_WRITE);
entry->write_cb = callback;
entry->write_priv = privdata;
}
return entry;
}
int event_get_fd(struct event_fd *entry)
{
return (entry != NULL) ? entry->fd: -1;
}
void event_remove_fd(struct event_fd *entry)
{
/* mark the event as deleted -> remove in select() loop */
entry->flags |= EVENT_DELETE;
}
static void add_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
{
ret->tv_usec = a->tv_usec + b->tv_usec;
ret->tv_sec = a->tv_sec + b->tv_sec;
if (ret->tv_usec >= 1000000) {
ret->tv_usec -= 1000000;
ret->tv_sec++;
}
}
static void sub_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
{
ret->tv_usec = a->tv_usec - b->tv_usec;
ret->tv_sec = a->tv_sec - b->tv_sec;
if (ret->tv_usec < 0) {
ret->tv_usec += 1000000;
ret->tv_sec--;
}
}
static int cmp_timeval(struct timeval *a, struct timeval *b)
{
if (a->tv_sec > b->tv_sec)
return -1;
if (a->tv_sec < b->tv_sec)
return 1;
if (a->tv_usec > b->tv_usec)
return -1;
if (a->tv_usec < b->tv_usec)
return 1;
return 0;
}
static void schedule_nextrun(struct event_timeout *entry, struct timeval *now)
{
add_timeval(&entry->nextrun, now, &entry->intervall);
struct event_timeout *search;
list_for_each_entry(search, &event_timeout_list, list) {
if (search->nextrun.tv_sec > entry->nextrun.tv_sec) {
list_add_tail(&entry->list, &search->list);
return;
} else if (search->nextrun.tv_sec == entry->nextrun.tv_sec &&
search->nextrun.tv_usec > entry->nextrun.tv_usec) {
list_add_tail(&entry->list, &search->list);
return;
}
}
list_add_tail(&entry->list, &event_timeout_list);
}
struct event_timeout * event_add_timeout(
struct timeval *timeout,
int (*callback)(int timerid, void *privdata),
int timerid,
void *privdata)
{
struct event_timeout *entry;
entry = malloc(sizeof(struct event_timeout));
if (entry == NULL) {
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
return NULL;
}
entry->flags = 0;
memcpy(&entry->intervall, timeout, sizeof(entry->intervall));
entry->callback = callback;
entry->timerid = timerid;
entry->privdata = privdata;
struct timeval now;
gettimeofday(&now, NULL);
schedule_nextrun(entry, &now);
return entry;
}
struct event_timeout * event_add_timeout_ms(
int timeout_ms,
int (*callback)(int timerid, void *privdata),
int timerid,
void *privdata)
{
struct timeval tv;
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
return event_add_timeout(&tv, callback, timerid, privdata);
}
void event_remove_timeout(struct event_timeout *entry)
{
/* mark the event as deleted -> remove in select() loop */
entry->flags |= EVENT_DELETE;
}
int event_loop(int (*pre_select_cb)(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata),
int (*post_select_cb)(int retval, void *readfds, void *writefds, void *privdata),
void *privdata)
{
while (1) {
/* default value if no application timeout is present */
struct timeval timeout = {
.tv_sec = -1,
.tv_usec = -1,
};
if (!list_empty(&event_timeout_list)) {
struct timeval now;
gettimeofday(&now, NULL);
struct event_timeout *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &event_timeout_list, list) {
if (entry->flags & EVENT_DELETE) {
list_del(&entry->list);
free(entry);
continue;
}
/* first timeout not elapsed, exit search (since list is sorted) */
if (cmp_timeval(&entry->nextrun, &now) == -1)
break;
/* remove event from list */
list_del(&entry->list);
/* execute callback, when callback returns 0 -> schedule event again */
if (entry->callback(entry->timerid, entry->privdata)) {
free(entry);
} else {
schedule_nextrun(entry, &now);
}
}
if (!list_empty(&event_timeout_list)) {
entry = list_entry(event_timeout_list.next, typeof(*entry), list);
/* calc select() timeout */
sub_timeval(&timeout, &entry->nextrun, &now);
}
}
struct event_fd *entry, *tmp;
int maxfd = -1;
fd_set readfds, writefds;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
list_for_each_entry_safe(entry, tmp, &event_fd_list, list) {
entry->flags &= ~EVENT_NEW;
if (entry->flags & EVENT_DELETE) {
list_del(&entry->list);
free(entry);
continue;
}
if (entry->flags & FD_READ)
FD_SET(entry->fd, &readfds);
if (entry->flags & FD_WRITE)
FD_SET(entry->fd, &writefds);
maxfd = (entry->fd > maxfd) ? entry->fd : maxfd;
}
maxfd++;
/* exit loop if callback returns true */
if (pre_select_cb != NULL && pre_select_cb(&maxfd, (void *)&readfds, (void *)&writefds, &timeout, privdata) != 0)
break;
int retval;
if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
retval = select(maxfd, &readfds, &writefds, NULL, NULL);
else
retval = select(maxfd, &readfds, &writefds, NULL, &timeout);
/* exit loop if callback returns true */
if (post_select_cb != NULL && post_select_cb(retval, (void *)&readfds, (void *)&writefds, privdata) != 0)
break;
if (retval < 0 && errno == EINTR) {
errno = 0;
continue;
} else if (retval < 0) {
log_print(LOG_ERROR, "%s(): select():", __FUNCTION__);
continue;
}
/* timeout */
if (retval == 0)
continue;
list_for_each_entry(entry, &event_fd_list, list) {
if (((entry->flags & (FD_READ | EVENT_NEW)) == FD_READ) && FD_ISSET(entry->fd, &readfds))
if (entry->read_cb(entry->fd, entry->read_priv) != 0)
entry->flags |= EVENT_DELETE;
if (((entry->flags & (FD_WRITE | EVENT_NEW)) == FD_WRITE) && FD_ISSET(entry->fd, &writefds))
if (entry->write_cb(entry->fd, entry->write_priv) != 0)
entry->flags |= EVENT_DELETE;
}
}
return 0;
}

51
event.h
View File

@ -1,51 +0,0 @@
#ifndef _EVENT_H_
#define _EVENT_H_
#include <sys/time.h>
#define EVENT_NEW 0x1000
#define EVENT_DELETE 0x2000
#define FD_READ 0x0001
#define FD_WRITE 0x0002
#define FD_TYPES (FD_READ | FD_WRITE)
#define event_add_readfd(entry, fd, callback, privdata) \
event_add_fd(entry, fd, FD_READ, callback, privdata)
#define event_add_writefd(entry, fd, callback, privdata) \
event_add_fd(entry, fd, FD_WRITE, callback, privdata)
/* inner details are not visible to external users (TODO: size unknown) */
struct event_fd;
struct event_timeout;
struct event_fd * event_add_fd(
struct event_fd *entry,
int fd,
int type,
int (*callback)(int fd, void *privdata),
void *privdata);
int event_get_fd(struct event_fd *entry);
void event_remove_fd(struct event_fd *entry);
struct event_timeout * event_add_timeout(
struct timeval *timeout,
int (*callback)(int timerid, void *privdata),
int timerid,
void *privdata);
struct event_timeout * event_add_timeout_ms(
int timeout_ms,
int (*callback)(int timerid, void *privdata),
int timerid,
void *privdata);
void event_remove_timeout(struct event_timeout *entry);
int event_loop(int (*pre_select_cb)(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata),
int (*post_select_cb)(int retval, void *readfds, void *writefds, void *privdata),
void *privdata);
#endif /* _EVENT_H_ */

View File

@ -1,37 +0,0 @@
/***************************************************************************
* Copyright (C) 10/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strsplit(char *string, char *delim, char **fields, int size)
{
int i = 0;
char *tmp, *ptr = string;
while ((fields[i] = strtok_r(ptr, delim, &tmp)) != NULL) {
ptr = NULL;
i++;
if (i >= size)
break;
}
return i;
}

View File

@ -1,8 +0,0 @@
#ifndef _HELPER_H_
#define _HELPER_H_
#define DFLT_DELIM " \n\t"
int strsplit(char *string, char *delim, char **fields, int size);
#endif /* _HELPER_H_ */

View File

@ -1,239 +0,0 @@
/***************************************************************************
* Copyright (C) 03/2010 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include "linebuffer.h"
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
struct lbuf {
size_t size;
size_t pos;
char *token;
char data[0];
};
/*
* creates linebuffer with given size
*/
struct lbuf * lbuf_create(size_t size)
{
struct lbuf *buf = malloc(sizeof(struct lbuf) + size);
if (buf == NULL)
return NULL;
buf->size = size;
buf->pos = 0;
return buf;
}
/*
* frees the linebuffer and all data in it
*/
void lbuf_free(struct lbuf *buf)
{
free(buf);
}
/*
* clears the linebuffer
* - returns the datasize it was holding
*/
int lbuf_clear(struct lbuf *buf)
{
int oldpos = buf->pos;
buf->pos = 0;
return oldpos;
}
/*
* get pointer to internal data
* - returns pointer to datasize
*/
char * lbuf_getdata(struct lbuf *buf, size_t *len)
{
if (len != NULL)
*len = buf->pos;
return buf->data;
}
/*
* appends data to the buffer
* - returns the number of bytes copied
*/
int lbuf_append(struct lbuf *buf, const char *src, size_t size)
{
int len = MIN(buf->size - buf->pos, size);
memcpy(buf->data + buf->pos, src, len);
buf->pos += len;
return len;
}
/*
* reads as much data as it can get from a FD
* - returns the number of bytes read, or -1 on error
*/
int lbuf_readfd(struct lbuf *buf, int fd)
{
int len = read(fd, buf->data + buf->pos, buf->size - buf->pos);
if (len <= 0)
return -1;
buf->pos += len;
return len;
}
/*
* parses as much data as it can get from a FD
* parses means: backspaces remove one byte from the end of the buffer
* - returns 0 on success, or -1 on error
*/
int lbuf_parsefd(struct lbuf *buf, int fd)
{
char tmp[32];
int len = read(fd, tmp, sizeof(tmp));
if (len <= 0)
return -1;
int i;
for (i = 0; i < len; i++) {
/* "understand" backspace */
if (tmp[i] == 0x08 && buf->pos > 0) {
buf->pos--;
/* copy */
} else if (tmp[i] >= ' ' || tmp[i] == '\n') {
*(buf->data + buf->pos++) = tmp[i];
}
if (buf->pos > buf->size)
return -1;
}
/* TODO: return bytes appended to buffer? */
return 0;
}
/*
* writes as much data as it can to a FD
* - returns the number of bytes written, or -1 on error
*/
int lbuf_writefd(struct lbuf *buf, int fd)
{
int len = write(fd, buf->data, buf->pos);
if (len <= 0)
return -1;
/* handle partial writes */
if (len != buf->pos)
memmove(buf->data, buf->data + len, buf->pos - len);
buf->pos -= len;
return len;
}
/*
* append va_list to buffer
* - returns number ob bytes appended, or -1 on error
*/
int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list az)
{
int len = vsnprintf(buf->data + buf->pos, buf->size - buf->pos, fmt, az);
if (len < 0 || len >= (buf->size - buf->pos))
return -1;
buf->pos += len;
return len;
}
/*
* printf into buffer
* - returns number of bytes appended, or -1 on error
*/
int lbuf_printf(struct lbuf *buf, const char *fmt, ...)
{
va_list az;
va_start(az, fmt);
int ret = lbuf_vprintf(buf, fmt, az);
va_end(az);
return ret;
}
/*
* get next non-empty token
* - returns pointer to next token
* - returns NULL if no delimter is found in buffer
*/
char * lbuf_gettok(struct lbuf *buf, const char *delim)
{
char *start = buf->data;
char *end = buf->data + buf->pos;
int dlen = strlen(delim);
while (1) {
buf->token = NULL;
/* find first delimiter in buffer */
int i;
for (i = 0; i < dlen; i++) {
char *tok = memchr(start, delim[i], end - start);
if (tok != NULL && (tok < buf->token || buf->token == NULL))
buf->token = tok;
}
/* nothing found */
if (buf->token == NULL)
return NULL;
/* delimter found on start pos -> skip empty token */
if (buf->token == start) {
start++;
if (start >= end)
return NULL;
} else {
/* non-empty token found, exit */
break;
}
}
/* overwrite token, return start ptr */
*(buf->token) = '\0';
return start;
}
/*
* release previous fetched line
* - returns number of remaining bytes in buffer
*/
int lbuf_freetok(struct lbuf *buf)
{
if (buf->token != NULL) {
buf->pos -= (buf->token - buf->data) +1;
memmove(buf->data, buf->token +1, buf->pos);
buf->token = NULL;
}
return buf->pos;
}

View File

@ -1,27 +0,0 @@
#ifndef _LINEBUFFER_H_
#define _LINEBUFFER_H_
#include <stdarg.h>
/* hide details */
struct lbuf;
struct lbuf * lbuf_create(size_t size);
void lbuf_free(struct lbuf *buf);
int lbuf_clear(struct lbuf *buf);
int lbuf_readfd(struct lbuf *buf, int fd);
int lbuf_parsefd(struct lbuf *buf, int fd);
int lbuf_writefd(struct lbuf *buf, int fd);
char * lbuf_getdata(struct lbuf *buf, size_t *len);
int lbuf_append(struct lbuf *buf, const char *src, size_t size);
int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list ap);
int lbuf_printf(struct lbuf *buf, const char *fmt, ...);
char * lbuf_gettok(struct lbuf *buf, const char *delim);
int lbuf_freetok(struct lbuf *buf);
#endif /* _LINEBUFFER_H_ */

View File

@ -1,10 +1,11 @@
/***************************************************************************
* Copyright (C) 07/2007 by Olaf Rempel *
* Copyright (C) 06/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
@ -18,98 +19,85 @@
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include "logging.h"
#define BUFSIZE 8192
static FILE *log_file = NULL;
static int log_prio = LOG_EVERYTIME;
static FILE *log_fd = NULL;
static char *buffer = NULL;
int log_print(int prio, const char *fmt, ...)
void log_print(int prio, const char *fmt, ...)
{
va_list az;
int len = 0, retval;
if (prio < log_prio)
return 0;
int len;
if (buffer == NULL) {
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
fprintf(stderr, "%s(): out of memory\n", __FUNCTION__);
return -1;
fprintf(stderr, "log_print: out of memory\nBailing out!\n");
exit(-1);
}
}
if (log_file != NULL) {
time_t tzgr;
time(&tzgr);
len += strftime(buffer, BUFSIZE, "%b %d %H:%M:%S :", localtime(&tzgr));
}
va_start(az, fmt);
len += vsnprintf(buffer + len, BUFSIZE - len, fmt, az);
len = vsnprintf(buffer, BUFSIZE, fmt, az);
va_end(az);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "log_print: arguments too long");
errno = 0;
return log_print(LOG_ERROR, "%s: arguments too long", __FUNCTION__);
return;
}
if (errno) {
len += snprintf(buffer + len, BUFSIZE - len, ": %s", strerror(errno));
errno = 0;
strncpy(buffer + len, ": ", BUFSIZE - len);
len += 2;
strncpy(buffer + len, strerror(errno), BUFSIZE - len);
}
retval = fprintf((log_file ? log_file : stderr), "%s\n", buffer);
fflush(log_file);
return retval;
if (log_fd) {
char tbuf[64];
time_t tzgr;
time(&tzgr);
strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr));
fprintf(log_fd, "%s %s\n", tbuf, buffer);
fflush(log_fd);
} else {
fprintf(stderr, "%s\n", buffer);
}
errno = 0;
}
void log_close(void)
static void log_close(void)
{
if (buffer) {
if (buffer)
free(buffer);
buffer = NULL;
}
if (log_file) {
fclose(log_file);
log_file = NULL;
}
fclose(log_fd);
}
int log_init(const char *logfile)
int log_init(char *logfile)
{
if (log_file != NULL)
log_close();
log_file = fopen(logfile, "a");
if (log_file == NULL) {
fprintf(stderr, "%s(): can not open logfile", __FUNCTION__);
return -1;
log_fd = fopen(logfile, "a");
if (log_fd == NULL) {
log_print(LOG_ERROR, "log_open('%s'): %s", logfile);
return 0;
}
if (fcntl(fileno(log_file), F_SETFD, FD_CLOEXEC) < 0) {
fprintf(stderr, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
fclose(log_file);
return -1;
if (atexit(log_close) != 0) {
log_print(LOG_ERROR, "log_open(): atexit()");
return 0;
}
log_prio = LOG_EVERYTIME;
return 0;
}
void log_setprio(int prio)
{
log_prio = prio;
log_print(LOG_EVERYTIME, "==========================");
return 1;
}

View File

@ -1,23 +1,16 @@
#ifndef _LOGGING_H_
#define _LOGGING_H_
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define LOG_DEBUG 5
#define LOG_INFO 4
#define LOG_NOTICE 3
#define LOG_WARN 2
#define LOG_ERROR 1
#define LOG_CRIT 0
#define LOG_EVERYTIME LOG_EMERG
#define LOG_ERROR LOG_ERR
#define LOG_WARN LOG_WARNING
#define LOG_EVERYTIME 0
int log_init(const char *logfile);
void log_close(void);
void log_setprio(int prio);
int log_print(int prio, const char *fmt, ... );
int log_init(char *logfile);
void log_print(int prio, const char *fmt, ... );
#endif /* _LOGGING_H_ */

206
network.c
View File

@ -1,206 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "configfile.h"
#include "event.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "network.h"
#include "plugins.h"
#include "rrdtool.h"
#include "sockaddr.h"
#define PKTSIZE 1400
struct net_entry {
struct list_head list;
struct event_fd *event;
struct sockaddr_in addr;
int socket;
};
static LIST_HEAD(srv_list);
static LIST_HEAD(cli_list);
static char *fwd_buf;
static int fwd_buf_len;
void net_submit_flush(void)
{
if (fwd_buf_len == 0)
return;
struct net_entry *entry;
list_for_each_entry(entry, &cli_list, list)
sendto(entry->socket, fwd_buf, fwd_buf_len, 0, (struct sockaddr *)&entry->addr, sizeof(entry->addr));
fwd_buf_len = 0;
}
int net_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
{
if (list_empty(&cli_list))
return 0;
int size = snprintf(fwd_buf + fwd_buf_len, PKTSIZE - fwd_buf_len, "%s:%s:%s:%d %s\n",
hostname, pluginname, filename, ds_id, data);
if (size < 0 || size >= PKTSIZE - fwd_buf_len) {
/* the complete buffer is already full */
if (fwd_buf_len == 0) {
log_print(LOG_ERROR, "net_submit(): arguments too long");
return -1;
}
/* flush & retry */
net_submit_flush();
return net_submit(hostname, pluginname, filename, ds_id, data);
}
fwd_buf_len += size;
return 0;
}
static int net_receive(int socket, void *privdata)
{
int recvsize;
if (ioctl(socket, FIONREAD, &recvsize) == -1) {
log_print(LOG_WARN, "net_receive(): ioctl(FIONREAD)");
return 0;
}
char *buf = malloc(recvsize);
if (buf == NULL) {
log_print(LOG_WARN, "net_receive(): out of memory");
return 0;
}
int size = recv(socket, buf, recvsize, 0);
if (size <= 0) {
log_print(LOG_WARN, "net_receive(): recv()");
free(buf);
return 0;
}
char *delim;
int pos = 0;
while ((delim = memchr(buf + pos, '\n', size - pos)) != NULL) {
*delim = '\0';
char *data[2];
int ret = strsplit(buf + pos, " ", data, 2);
pos = (delim - buf) +1;
if (ret != 2) {
log_print(LOG_ERROR, "net_receive(): abort data-split");
continue;
}
char *part[4];
ret = strsplit(data[0], ":", part, 4);
if (ret != 4) {
log_print(LOG_ERROR, "net_receive(): abort header-split");
continue;
}
rrd_submit(part[0], part[1], part[2], atoi(part[3]), data[1]);
}
free(buf);
return 0;
}
static struct net_entry * create_net_entry(const char *value)
{
struct net_entry *entry = malloc(sizeof(struct net_entry));
if (entry == NULL)
return NULL;
if (parse_sockaddr(value, &entry->addr) < 0) {
free(entry);
return NULL;
}
entry->socket = socket(PF_INET, SOCK_DGRAM, 0);
if (entry->socket < 0) {
free(entry);
return NULL;
}
return entry;
}
static int net_init_srv_cb(const char *value, void *privdata)
{
struct net_entry *entry = create_net_entry(value);
if (entry == NULL) {
log_print(LOG_ERROR, "net_init_srv_cb(): can not create net_entry");
return -1;
}
if (bind(entry->socket, (struct sockaddr *)&entry->addr, sizeof(entry->addr)) < 0) {
log_print(LOG_ERROR, "net_init_srv_cb(): bind()");
close(entry->socket);
free(entry);
return -1;
}
entry->event = event_add_readfd(NULL, entry->socket, net_receive, NULL);
list_add(&entry->list, &srv_list);
log_print(LOG_INFO, "listen on %s", get_sockaddr_buf(&entry->addr));
return 0;
}
static int net_init_cli_cb(const char *value, void *privdata)
{
struct net_entry *entry = create_net_entry(value);
if (entry == NULL) {
log_print(LOG_ERROR, "net_init_cli_cb(): can not create net_entry");
return -1;
}
list_add(&entry->list, &cli_list);
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&entry->addr));
return 0;
}
int net_init(void)
{
config_get_strings("global", "listen", net_init_srv_cb, NULL);
config_get_strings("global", "forward", net_init_cli_cb, NULL);
fwd_buf = malloc(PKTSIZE);
if (fwd_buf == NULL) {
log_print(LOG_ERROR, "net_submit(): out of memory");
return -1;
}
return 0;
}
void net_close(void) {
struct net_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &cli_list, list) {
list_del(&entry->list);
close(entry->socket);
free(entry);
}
list_for_each_entry_safe(entry, tmp, &srv_list, list) {
list_del(&entry->list);
event_remove_fd(entry->event);
close(entry->socket);
free(entry);
}
fwd_buf_len = 0;
if (fwd_buf != NULL)
free(fwd_buf);
}

View File

@ -1,12 +0,0 @@
#ifndef _NETWORK_H_
#define _NETWORK_H_
#include "plugins.h"
int net_init(void);
void net_close(void);
int net_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data);
void net_submit_flush(void);
#endif /* _NETWORK_H_ */

View File

@ -21,58 +21,62 @@
#include <stdlib.h>
#include <string.h>
#include "helper.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *ds_def = {
"DS:entries:GAUGE:15:0:U "
"DS:searched:DERIVE:15:0:U "
"DS:found:DERIVE:15:0:U "
"DS:new:DERIVE:15:0:U "
"DS:invalid:DERIVE:15:0:U "
"DS:ignore:DERIVE:15:0:U "
"DS:delete:DERIVE:15:0:U "
"DS:delete_list:DERIVE:15:0:U "
"DS:insert:DERIVE:15:0:U "
"DS:insert_failed:DERIVE:15:0:U "
"DS:drop:DERIVE:15:0:U "
"DS:early_drop:DERIVE:15:0:U "
"DS:icmp_error:DERIVE:15:0:U "
"DS:expect_new:DERIVE:15:0:U "
"DS:expect_create:DERIVE:15:0:U "
"DS:expect_delete:DERIVE:15:0:U "
static char *ds_def[] = {
"DS:entries:GAUGE:%d:0:U",
"DS:searched:DERIVE:%d:0:U",
"DS:found:DERIVE:%d:0:U",
"DS:new:DERIVE:%d:0:U",
"DS:invalid:DERIVE:%d:0:U",
"DS:ignore:DERIVE:%d:0:U",
"DS:delete:DERIVE:%d:0:U",
"DS:delete_list:DERIVE:%d:0:U",
"DS:insert:DERIVE:%d:0:U",
"DS:insert_failed:DERIVE:%d:0:U",
"DS:drop:DERIVE:%d:0:U",
"DS:early_drop:DERIVE:%d:0:U",
"DS:icmp_error:DERIVE:%d:0:U",
"DS:expect_new:DERIVE:%d:0:U",
"DS:expect_create:DERIVE:%d:0:U",
"DS:expect_delete:DERIVE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp;
char *val[16], filename[16];
char *buffer, *val[16], filename[16];
unsigned long long arr[16];
int i, len, cpu = 0;
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin ctstat: out of memory");
return;
}
fp = fopen("/proc/net/stat/ip_conntrack", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin ctstat");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
if (!strncmp(buffer, "entries", 7))
continue;
if (strsplit(buffer, " \t\n", val, 16) != 16)
if (strsplit(buffer, val, 16) != 16)
continue;
for (i = 0; i < 16; i++)
@ -92,26 +96,12 @@ static int probe(void)
cpu++;
}
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "ctstat",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -20,46 +20,51 @@
#include <stdio.h>
#include <stdlib.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
struct sammler_plugin plugin;
static const char *ds_def = {
"DS:1min:GAUGE:15:0:U "
"DS:5min:GAUGE:15:0:U "
"DS:15min:GAUGE:15:0:U "
static char *ds_def[] = {
"DS:1min:GAUGE:%d:0:U",
"DS:5min:GAUGE:%d:0:U",
"DS:15min:GAUGE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp = fopen("/proc/loadavg", "r");
FILE *fp;
char buffer[32];
char *val[3];
fp = fopen("/proc/loadavg", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin load: fopen()");
return -1;
log_print(LOG_WARN, "plugin load");
return;
}
double load1, load5, load15;
if (fscanf(fp, "%lf %lf %lf", &load1, &load5, &load15) != 3) {
log_print(LOG_WARN, "plugin load: fscanf()");
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
log_print(LOG_WARN, "plugin load");
fclose(fp);
return -1;
return;
}
fclose(fp);
probe_submit(&plugin, "load.rrd", 0, "%.02lf:%.02lf:%.02lf", load1, load5, load15);
return 0;
if (strsplit(buffer, val, 3) != 3)
return;
probe_submit(&plugin, "load.rrd", 0, "%s:%s:%s", val[0], val[1], val[2]);
}
struct sammler_plugin plugin = {
.name = "load",
.interval = 10,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -21,31 +21,30 @@
#include <stdlib.h>
#include <string.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
#define DS_MEMORY 1
#define DS_SWAP 2
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *mem_ds_def = {
"DS:total:GAUGE:15:0:U "
"DS:free:GAUGE:15:0:U "
"DS:buffers:GAUGE:15:0:U "
"DS:cached:GAUGE:15:0:U "
static char *mem_ds_def[] = {
"DS:total:GAUGE:%d:0:U",
"DS:free:GAUGE:%d:0:U",
"DS:buffers:GAUGE:%d:0:U",
"DS:cached:GAUGE:%d:0:U",
NULL
};
static const char *swap_ds_def = {
"DS:total:GAUGE:15:0:U "
"DS:free:GAUGE:15:0:U "
static char *swap_ds_def[] = {
"DS:total:GAUGE:%d:0:U",
"DS:free:GAUGE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
switch (ds_id) {
case DS_MEMORY:
@ -68,17 +67,23 @@ struct meminfo_ {
unsigned long long swapfree;
};
static int probe(void)
static void probe(void)
{
FILE *fp;
char *buffer;
struct meminfo_ meminfo;
memset(&meminfo, 0, sizeof(meminfo));
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin memory: out of memory");
return;
}
fp = fopen("/proc/meminfo", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin memory");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
@ -109,26 +114,12 @@ static int probe(void)
meminfo.swaptotal, meminfo.swapfree);
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "memory",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -19,92 +19,58 @@
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mntent.h>
#include <sys/vfs.h>
#include <string.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define MAXFSNAME 16
struct sammler_plugin plugin;
static const char *ds_def = {
"DS:block_total:GAUGE:15:0:U "
"DS:block_free:GAUGE:15:0:U "
static char *ds_def[] = {
"DS:block_total:GAUGE:%d:0:U",
"DS:block_free:GAUGE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static char * get_valid_fs(int *xcnt)
static void probe(void)
{
FILE *fp = fopen("/proc/filesystems", "r");
if (fp == NULL)
return NULL;
FILE *fp;
struct mntent *mnt;
struct statfs fs;
char *slash, filename[64];
int len;
int cnt = 0;
char buffer[64];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
if (!strncmp(buffer, "nodev", 5))
continue;
cnt++;
}
char *valid_arr = malloc(cnt * MAXFSNAME);
if (valid_arr == NULL)
return NULL;
rewind(fp);
int i = 0;
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
if (!strncmp(buffer, "nodev", 5))
continue;
char *end = memccpy(valid_arr + (i++ * MAXFSNAME), buffer +1, '\n', MAXFSNAME);
*(end -1) = '\0';
}
fclose(fp);
*xcnt = cnt;
return valid_arr;
}
static int probe(void)
{
FILE *fp = setmntent("/etc/mtab", "r");
fp = setmntent("/etc/mtab", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin mount");
return -1;
return;
}
int cnt;
char *valid_arr = get_valid_fs(&cnt);
if (valid_arr == NULL) {
log_print(LOG_WARN, "plugin mount");
endmntent(fp);
return -1;
}
struct mntent *mnt;
while ((mnt = getmntent(fp)) != NULL) {
int i, valid = 0;
for (i = 0; i < cnt; i++)
if (strncmp(mnt->mnt_type, valid_arr + (i * MAXFSNAME), MAXFSNAME) == 0)
valid = 1;
if (valid == 0)
if (!strcmp(mnt->mnt_fsname, "none"))
continue;
if (!strcmp(mnt->mnt_fsname, "proc"))
continue;
if (!strcmp(mnt->mnt_fsname, "sysfs"))
continue;
if (!strcmp(mnt->mnt_fsname, "udev"))
continue;
if (!strcmp(mnt->mnt_fsname, "devpts"))
continue;
if (!strcmp(mnt->mnt_type, "nfs"))
continue;
struct statfs fs;
if (statfs(mnt->mnt_dir, &fs) == -1) {
log_print(LOG_WARN, "plugin mount: statfs(%s)", mnt->mnt_dir);
continue;
@ -113,14 +79,13 @@ static int probe(void)
if (fs.f_blocks == 0)
continue;
char *slash = mnt->mnt_fsname;
slash = mnt->mnt_fsname;
while (slash && (slash = strchr(slash, '/'))) {
slash = strchr(slash, '/');
*slash++ = '_';
}
char filename[64];
int len = snprintf(filename, sizeof(filename), "mount%s.rrd", mnt->mnt_fsname);
len = snprintf(filename, sizeof(filename), "mount%s.rrd", mnt->mnt_fsname);
if (len < 0 || len >= sizeof(filename)) {
log_print(LOG_WARN, "plugin mount: file name too long", mnt->mnt_fsname);
continue;
@ -130,15 +95,12 @@ static int probe(void)
fs.f_blocks * (fs.f_bsize /1024),
fs.f_bfree * (fs.f_bsize /1024));
}
free(valid_arr);
endmntent(fp);
return 0;
}
struct sammler_plugin plugin = {
.name = "mount",
.interval = 10,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -21,39 +21,43 @@
#include <stdlib.h>
#include <string.h>
#include "helper.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *ds_def = {
"DS:byte_in:COUNTER:15:0:U "
"DS:byte_out:COUNTER:15:0:U "
"DS:pkt_in:COUNTER:15:0:U "
"DS:pkt_out:COUNTER:15:0:U "
static char *ds_def[] = {
"DS:byte_in:COUNTER:%d:0:U",
"DS:byte_out:COUNTER:%d:0:U",
"DS:pkt_in:COUNTER:%d:0:U",
"DS:pkt_out:COUNTER:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp;
char *stats, *device;
char *buffer, *stats, *device;
char *val[16], filename[32];
int len;
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin netdev: out of memory");
return;
}
fp = fopen("/proc/net/dev", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin netdev");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
@ -70,7 +74,7 @@ static int probe(void)
if (*device == '\0')
continue;
if (strsplit(stats, " \t\n", val, 16) != 16)
if (strsplit(stats, val, 16) != 16)
continue;
len = snprintf(filename, sizeof(filename), "net-%s.rrd", device);
@ -81,26 +85,12 @@ static int probe(void)
val[0], val[8], val[1], val[9]);
}
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "netdev",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -20,44 +20,49 @@
#include <stdio.h>
#include <stdlib.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
struct sammler_plugin plugin;
static const char *ds_def = {
"DS:entropy:GAUGE:15:0:U "
static char *ds_def[] = {
"DS:entropy:GAUGE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp = fopen("/proc/sys/kernel/random/entropy_avail", "r");
FILE *fp;
char buffer[32];
char *val[1];
fp = fopen("/proc/sys/kernel/random/entropy_avail", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin random: fopen()");
return -1;
log_print(LOG_WARN, "plugin random");
return;
}
int entropy;
if (fscanf(fp, "%d", &entropy) != 1) {
log_print(LOG_WARN, "plugin random: fopen()");
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
log_print(LOG_WARN, "plugin random");
fclose(fp);
return -1;
return;
}
fclose(fp);
probe_submit(&plugin, "random.rrd", 0, "%d", entropy);
return 0;
if (strsplit(buffer, val, 1) != 1)
return;
probe_submit(&plugin, "random.rrd", 0, "%s", val[0]);
}
struct sammler_plugin plugin = {
.name = "random",
.interval = 10,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -21,74 +21,63 @@
#include <stdlib.h>
#include <string.h>
#include "helper.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define DS_STAT 1
#define DS_GC 2
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *ds_def_stat = {
"DS:in_hit:DERIVE:15:0:U "
"DS:in_slow_tot:DERIVE:15:0:U "
"DS:in_slow_mc:DERIVE:15:0:U "
"DS:in_no_route:DERIVE:15:0:U "
"DS:in_brd:DERIVE:15:0:U "
"DS:in_martian_dst:DERIVE:15:0:U "
"DS:in_martian_src:DERIVE:15:0:U "
"DS:out_hit:DERIVE:15:0:U "
"DS:out_slow_tot:DERIVE:15:0:U "
"DS:out_slow_mc:DERIVE:15:0:U "
"DS:in_hlist_search:DERIVE:15:0:U "
"DS:out_hlist_search:DERIVE:15:0:U "
static char *ds_def[] = {
"DS:entries:GAUGE:%d:0:U",
"DS:in_hit:DERIVE:%d:0:U",
"DS:in_slow_tot:DERIVE:%d:0:U",
"DS:in_slow_mc:DERIVE:%d:0:U",
"DS:in_no_route:DERIVE:%d:0:U",
"DS:in_brd:DERIVE:%d:0:U",
"DS:in_martian_dst:DERIVE:%d:0:U",
"DS:in_martian_src:DERIVE:%d:0:U",
"DS:out_hit:DERIVE:%d:0:U",
"DS:out_slow_tot:DERIVE:%d:0:U",
"DS:out_slow_mc:DERIVE:%d:0:U",
"DS:gc_total:DERIVE:%d:0:U",
"DS:gc_ignored:DERIVE:%d:0:U",
"DS:gc_goal_miss:DERIVE:%d:0:U",
"DS:gc_dst_overflow:DERIVE:%d:0:U",
"DS:in_hlist_search:DERIVE:%d:0:U",
"DS:out_hlist_search:DERIVE:%d:0:U",
NULL
};
static const char *ds_def_gc = {
"DS:entries:GAUGE:15:0:U "
"DS:gc_total:DERIVE:15:0:U "
"DS:gc_ignored:DERIVE:15:0:U "
"DS:gc_goal_miss:DERIVE:15:0:U "
"DS:gc_dst_overflow:DERIVE:15:0:U "
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
switch (ds_id) {
case DS_STAT:
return ds_def_stat;
case DS_GC:
return ds_def_gc;
default:
return NULL;
}
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp;
char *val[17], filename[16];
char *buffer, *val[17], filename[16];
unsigned long long arr[17];
int i, len, cpu = 0;
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin rtstat: out of memory");
return;
}
fp = fopen("/proc/net/stat/rt_cache", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin rtstat");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
if (!strncmp(buffer, "entries", 7))
continue;
if (strsplit(buffer, " \t\n", val, 17) != 17)
if (strsplit(buffer, val, 17) != 17)
continue;
for (i = 0; i < 17; i++)
@ -98,43 +87,22 @@ static int probe(void)
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_STAT,
"%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
arr[1], arr[2], arr[3], arr[4],
arr[5], arr[6], arr[7], arr[8],
arr[9], arr[10], arr[15], arr[16]);
len = snprintf(filename, sizeof(filename), "rtcache-%d.rrd", cpu);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_GC,
"%llu:%llu:%llu:%llu:%llu",
arr[0], arr[11], arr[12], arr[13], arr[14]);
probe_submit(&plugin, filename, 0,
"%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
arr[0], arr[1], arr[2], arr[3],
arr[4], arr[5], arr[6], arr[7],
arr[8], arr[9], arr[10], arr[11],
arr[12], arr[13], arr[14], arr[15],
arr[16]);
cpu++;
}
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "rtstat",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -21,37 +21,34 @@
#include <stdlib.h>
#include <string.h>
#include "helper.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
#define DS_CPU 1
#define DS_PROC 2
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *cpu_ds_def = {
"DS:user:COUNTER:15:0:U "
"DS:nice:COUNTER:15:0:U "
"DS:system:COUNTER:15:0:U "
"DS:idle:COUNTER:15:0:U "
"DS:iowait:COUNTER:15:0:U "
"DS:irq:COUNTER:15:0:U "
"DS:softirq:COUNTER:15:0:U "
"DS:steal:COUNTER:15:0:U "
static char *cpu_ds_def[] = {
"DS:user:COUNTER:%d:0:U",
"DS:nice:COUNTER:%d:0:U",
"DS:syst:COUNTER:%d:0:U",
"DS:idle:COUNTER:%d:0:U",
"DS:wait:COUNTER:%d:0:U",
"DS:intr:COUNTER:%d:0:U",
"DS:sitr:COUNTER:%d:0:U",
NULL
};
static const char *proc_ds_def = {
"DS:intr:COUNTER:15:0:U "
"DS:ctxt:COUNTER:15:0:U "
"DS:fork:COUNTER:15:0:U "
static char *proc_ds_def[] = {
"DS:intr:COUNTER:%d:0:U",
"DS:ctxt:COUNTER:%d:0:U",
"DS:fork:COUNTER:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
switch (ds_id) {
case DS_CPU:
@ -71,17 +68,23 @@ struct proc_ {
unsigned long long fork;
};
static int probe(void)
static void probe(void)
{
FILE *fp;
char *buffer;
struct proc_ proc;
memset(&proc, 0, sizeof(proc));
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin stat: out of memory");
return;
}
fp = fopen("/proc/stat", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin stat");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
@ -99,20 +102,21 @@ static int probe(void)
strncpy(filename, "cpu.rrd", sizeof(filename));
}
numfields = strsplit(buffer, " \t\n", val, 9);
numfields = strsplit(buffer, val, 9);
if (numfields < 5)
continue;
else if (numfields == 5)
val[5] = val[6] = val[7] = val[8] = "0";
if (numfields >= 8) {
probe_submit(&plugin, filename, DS_CPU,
"%s:%s:%s:%s:%s:%s:%s",
val[1], val[2], val[3], val[4],
val[5], val[6], val[7]);
else if (numfields == 8)
val[8] = "0";
probe_submit(&plugin, filename, DS_CPU,
"%s:%s:%s:%s:%s:%s:%s:%s",
val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8]);
} else {
probe_submit(&plugin, filename, DS_CPU,
"%s:%s:%s:%s:0:0:0",
val[1], val[2], val[3], val[4]);
}
} else if (!strncmp(buffer, "intr", 4)) {
proc.intr = atoll(buffer + 5);
@ -129,26 +133,12 @@ static int probe(void)
proc.intr, proc.ctxt, proc.fork);
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "stat",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -20,45 +20,50 @@
#include <stdio.h>
#include <stdlib.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
struct sammler_plugin plugin;
static const char *ds_def = {
"DS:uptime:GAUGE:15:0:U "
"DS:idletime:GAUGE:15:0:U "
static char *ds_def[] = {
"DS:uptime:GAUGE:%d:0:U",
"DS:idletime:GAUGE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
static void probe(void)
{
FILE *fp = fopen("/proc/uptime", "r");
FILE *fp;
char buffer[32];
char *val[2];
fp = fopen("/proc/uptime", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin uptime: fopen()");
return -1;
log_print(LOG_WARN, "plugin uptime");
return;
}
double uptime, idletime;
if (fscanf(fp, "%lf %lf\n", &uptime, &idletime) != 2) {
log_print(LOG_WARN, "plugin uptime: fscanf()");
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
log_print(LOG_WARN, "plugin uptime");
fclose(fp);
return -1;
return;
}
fclose(fp);
probe_submit(&plugin, "uptime.rrd", 0, "%.02lf:%.02lf", uptime, idletime);
return 0;
if (strsplit(buffer, val, 2) != 2)
return;
probe_submit(&plugin, "uptime.rrd", 0, "%s:%s", val[0], val[1]);
}
struct sammler_plugin plugin = {
.name = "uptime",
.interval = 10,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -21,24 +21,22 @@
#include <stdlib.h>
#include <string.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *ds_def = {
"DS:pgalloc_high:DERIVE:15:0:U "
"DS:pgalloc_normal:DERIVE:15:0:U "
"DS:pgalloc_dma:DERIVE:15:0:U "
"DS:pgfree:DERIVE:15:0:U "
"DS:pgfault:DERIVE:15:0:U "
static char *ds_def[] = {
"DS:pgalloc_high:DERIVE:%d:0:U",
"DS:pgalloc_normal:DERIVE:%d:0:U",
"DS:pgalloc_dma:DERIVE:%d:0:U",
"DS:pgfree:DERIVE:%d:0:U",
"DS:pgfault:DERIVE:%d:0:U",
NULL
};
static const char * get_ds(int ds_id)
static char ** get_ds(int ds_id)
{
return ds_def;
}
@ -51,17 +49,23 @@ struct vmstat_ {
unsigned long long pgfault;
};
static int probe(void)
static void probe(void)
{
FILE *fp;
char *buffer;
struct vmstat_ vmstat;
memset(&vmstat, 0, sizeof(vmstat));
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_WARN, "plugin vmstat: out of memory");
return;
}
fp = fopen("/proc/vmstat", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin vmstat");
return -1;
free(buffer);
return;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
@ -86,26 +90,12 @@ static int probe(void)
vmstat.pgalloc_dma, vmstat.pgfree, vmstat.pgfault);
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "vmstat",
.interval = 10,
.init = &init,
.fini = &fini,
.version = 1,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,73 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "logging.h"
int pidfile_create(const char *filename)
{
int fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0644);
if (fd < 0)
return -1;
char buf[8];
int len = snprintf(buf, sizeof(buf), "%d", getpid());
write(fd, buf, len);
close(fd);
return 0;
}
int pidfile_remove(const char *filename)
{
return unlink(filename);
}
pid_t pidfile_check(const char *filename, int remove_stale)
{
int fd = open(filename, O_RDWR);
if (fd < 0) {
if (errno == ENOENT) {
errno = 0;
return 0;
}
return -1;
}
char buf[9];
int len = read(fd, buf, sizeof(buf) -1);
buf[len] = '\0';
close(fd);
char *tmp;
pid_t pid = strtol(buf, &tmp, 10);
if (len == 0 || tmp == buf)
pid = -1;
/* just return the pid */
if (!remove_stale)
return pid;
/* invalid pid, remove stale file */
if (pid == -1) {
pidfile_remove(filename);
return 0;
}
/* check if pid is still running */
if (kill(pid, 0) == 0 || errno != ESRCH) {
errno = 0;
return pid;
}
errno = 0;
pidfile_remove(filename);
return 0;
}

View File

@ -1,11 +0,0 @@
#ifndef _PIDFILE_H_
#define _PIDFILE_H_
#include <sys/types.h>
int pidfile_create(const char *filename);
int pidfile_remove(const char *filename);
pid_t pidfile_check(const char *filename, int remove_stale);
#endif // _PIDFILE_H_

203
plugins.c
View File

@ -22,127 +22,146 @@
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include <stdarg.h>
#include "list.h"
#include "configfile.h"
#include "event.h"
#include "logging.h"
#include "network.h"
#include "plugins.h"
#include "config.h"
#include "logging.h"
#include "rrdtool.h"
#define FLAGS_ACTIVE 0x01
#define BUFSIZE 1024
static LIST_HEAD(plugin_list);
static struct event_timeout *probe_event;
static int plugin_init_cb(const char *filename, void *privdata)
static void plugin_load(char *filename)
{
const char *plugin_dir = (const char *)privdata;
struct sammler_plugin *plugin = NULL;
static char *plugin_dir;
char *fullname = malloc(PATH_MAX);
if (fullname == NULL) {
log_print(LOG_ERROR, "plugin_init_cb(): out of memory");
return -1;
char *buffer;
void *tmp;
int len;
if (plugin_dir == NULL)
plugin_dir = config_get_string("global", "plugin_dir", ".");
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "plugin_load: out of memory");
return;
}
int len = snprintf(fullname, PATH_MAX, "%s/%s", plugin_dir, filename);
if (len < 0 || len >= PATH_MAX) {
log_print(LOG_ERROR, "plugin_init_cb(): file name too long: %s/%s", plugin_dir, filename);
free(fullname);
return -1;
len = snprintf(buffer, BUFSIZE, "%s/%s", plugin_dir, filename);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "plugin_load: file name too long: %s/%s", plugin_dir, filename);
free(buffer);
return;
}
dlerror();
void *dlhandle = dlopen(fullname, RTLD_NOW);
if (dlhandle == NULL) {
log_print(LOG_ERROR, "plugin_init_cb(): dlopen: %s", dlerror());
free(fullname);
return -1;
tmp = dlopen(buffer, RTLD_NOW);
if (tmp == NULL) {
log_print(LOG_ERROR, "plugin_load: dlopen: %s", dlerror());
free(buffer);
return;
}
free(fullname);
struct sammler_plugin *plugin = dlsym(dlhandle, "plugin");
plugin = dlsym(tmp, "plugin");
if (plugin == NULL) {
log_print(LOG_ERROR, "plugin_init_cb(): failed to load '%s'", filename);
dlclose(dlhandle);
return -1;
log_print(LOG_ERROR, "plugin_load: failed to load '%s'", filename);
dlclose(tmp);
free(buffer);
return;
}
if (plugin->init != NULL && (plugin->init() != 0)) {
log_print(LOG_ERROR, "plugin_init_cb(): Plugin '%s': init() failed", plugin->name);
dlclose(dlhandle);
return -1;
}
log_print(LOG_INFO, "Plugin '%s' loaded", plugin->name);
plugin->lastprobe = 0;
plugin->flags = FLAGS_ACTIVE;
plugin->dlhandle = dlhandle;
log_print(LOG_INFO, "Plugin '%s' (v%d) loaded", plugin->name, plugin->version);
list_add_tail(&plugin->list, &plugin_list);
return 0;
free(buffer);
return;
}
static int plugins_probe(int timerid, void *privdata)
void plugin_load_all()
{
time_t now;
time(&now);
struct conf_section *section;
struct conf_tupel *tupel;
section = config_get_section("global");
if (section == NULL)
return;
list_for_each_entry(tupel, &section->tupel, list)
if (!strcmp(tupel->option, "plugin"))
plugin_load(tupel->parameter);
}
void plugins_probe(void)
{
struct sammler_plugin *plugin;
list_for_each_entry(plugin, &plugin_list, list)
plugin->probe();
}
char ** plugins_get_ds(char *name, int version, int ds_id)
{
struct sammler_plugin *plugin;
list_for_each_entry(plugin, &plugin_list, list) {
if (!(plugin->flags & FLAGS_ACTIVE))
if (strcmp(plugin->name, name))
continue;
if (plugin->lastprobe + plugin->interval <= now) {
if (plugin->probe() != 0) {
log_print(LOG_ERROR, "plugin_probe(): plugin '%s' disabled", plugin->name);
plugin->flags &= ~FLAGS_ACTIVE;
}
plugin->lastprobe = now;
}
}
if (plugin->version != version)
continue;
net_submit_flush();
return 0;
}
int plugin_init(void)
{
const char *plugin_dir = config_get_string("global", "plugin_dir", "plugins");
int cnt = config_get_strings("global", "plugin", plugin_init_cb, (void *)plugin_dir);
if (cnt == 0) {
log_print(LOG_ERROR, "plugin_init(): no working plugins");
return -1;
}
probe_event = event_add_timeout_ms(1000, plugins_probe, 0, NULL);
return 0;
}
int plugin_close(void)
{
struct sammler_plugin *plugin, *tmp;
list_for_each_entry_safe(plugin, tmp, &plugin_list, list) {
list_del(&plugin->list);
if (plugin->fini != NULL && plugin->fini() != 0)
log_print(LOG_ERROR, "plugin_close(): Plugin '%s': fini() failed", plugin->name);
dlclose(plugin->dlhandle);
}
event_remove_timeout(probe_event);
return 0;
}
struct sammler_plugin * plugin_lookup(const char *name)
{
struct sammler_plugin *plugin;
list_for_each_entry(plugin, &plugin_list, list) {
if (!strcmp(plugin->name, name))
return plugin;
return plugin->get_ds(ds_id);
}
return NULL;
}
void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... )
{
va_list az;
char *buffer;
int len;
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "probe_submit: out of memory");
return;
}
va_start(az, fmt);
len = vsnprintf(buffer, BUFSIZE, fmt, az);
va_end(az);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "probe_submit: %s arguments too long", plugin->name);
free(buffer);
return;
}
rrd_submit(plugin->name, plugin->version, filename, ds_id, buffer);
// net_submit(plugin->name, plugin->version, filename, ds_id, buffer);
free(buffer);
}
int strsplit(char *string, char **fields, size_t size)
{
size_t i = 0;
char *ptr = string;
while ((fields[i] = strtok(ptr, " \n\t")) != NULL) {
ptr = NULL;
i++;
if (i >= size)
break;
}
return i;
}

View File

@ -1,30 +1,25 @@
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
#include <time.h>
#include "list.h"
#include "logging.h"
struct sammler_plugin {
struct list_head list;
void *dlhandle;
const char *name;
/* timing */
unsigned int interval;
time_t lastprobe;
/* flags */
int flags;
int (*init) (void);
int (*fini) (void);
int (*probe) (void);
const char * (*get_ds) (int ds_id);
char *name;
int version;
void (*probe) (void);
char ** (*get_ds) (int ds_id);
};
int plugin_init(void);
int plugin_close(void);
void plugin_load_all(void);
struct sammler_plugin * plugin_lookup(const char *name);
void plugins_probe(void);
char ** plugins_get_ds(char *plugin, int version, int ds_id);
void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... );
int strsplit(char *string, char **fields, size_t size);
#endif /* _PLUGINS_H_ */

View File

@ -1,106 +0,0 @@
/***************************************************************************
* Copyright (C) 04/2009 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "configfile.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
struct sammler_plugin plugin;
static const char *socket_path;
static const char *ds_def = {
"DS:ibat:GAUGE:15:U:U "
"DS:ubat:GAUGE:15:0:U "
"DS:uin:GAUGE:15:0:U "
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1) {
log_print(LOG_WARN, "plugin alixusv: socket()");
return -1;
}
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
int len = sizeof(addr.sun_family) + strlen(addr.sun_path);
if (connect(sockfd, (struct sockaddr *)&addr, len) < 0) {
log_print(LOG_ERROR, "plugin alixusv: connect(%s)", addr.sun_path);
close(sockfd);
return 0;
}
char buf[64] = "status";
write(sockfd, buf, strlen(buf));
len = read(sockfd, buf, sizeof(buf));
if (len <= 0) {
log_print(LOG_ERROR, "plugin alixusv: read()");
close(sockfd);
return -1;
}
close(sockfd);
char *field[4];
if (strsplit(buf, ": \t\n", field, 4) != 4)
return -1;
int ibat = strtoll(field[1], NULL, 10);
int ubat = strtoll(field[2], NULL, 10);
int uin = strtoll(field[3], NULL, 10);
probe_submit(&plugin, "alixusv.rrd", 0, "%d:%d:%d", ibat, ubat, uin);
return 0;
}
static int init(void)
{
socket_path = config_get_string("p_alixusv", "socket", NULL);
return (socket_path == NULL) ? -1 : 0;
}
struct sammler_plugin plugin = {
.name = "alixusv",
.interval = 10,
.init = &init,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,223 +0,0 @@
/***************************************************************************
* Copyright (C) 10/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <curl/curl.h>
#include "configfile.h"
#include "helper.h"
#include "linebuffer.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 8192
struct sammler_plugin plugin;
struct server_entry {
struct list_head list;
CURL *handle;
char *name;
};
static LIST_HEAD(server_list);
static const char *ds_def = {
"DS:total_accesses:COUNTER:90:0:U "
"DS:total_kbytes:COUNTER:90:0:U "
"DS:busy_workers:GAUGE:90:0:U "
"DS:idle_workers:GAUGE:90:0:U "
};
struct stats {
uint64_t total_accesses;
uint64_t total_kbytes;
uint64_t busy_workers;
uint64_t idle_workers;
};
static struct lbuf * rxbuf;
static const char * get_ds(int ds_id)
{
return ds_def;
}
static size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
lbuf_append(rxbuf, buffer, realsize);
return realsize;
}
static int probe(void)
{
struct server_entry *entry;
list_for_each_entry(entry, &server_list, list) {
lbuf_clear(rxbuf);
int ret = curl_easy_perform(entry->handle);
if (ret != 0) {
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
continue;
}
struct stats stats;
memset(&stats, 0, sizeof(stats));
char *line;
while ((line = lbuf_gettok(rxbuf, "\r\n")) != NULL) {
char *part[2];
strsplit(line, ":", part, 2);
if (!strcmp(part[0], "Total Accesses"))
stats.total_accesses = atoll(part[1]);
else if (!strcmp(part[0], "Total kBytes"))
stats.total_kbytes = atoll(part[1]);
else if (!strcmp(part[0], "BusyWorkers") || !strcmp(part[0], "BusyServers"))
stats.busy_workers = atoll(part[1]);
else if (!strcmp(part[0], "IdleWorkers") || !strcmp(part[0], "IdleServers"))
stats.idle_workers = atoll(part[1]);
lbuf_freetok(rxbuf);
}
char filename[32];
int len = snprintf(filename, sizeof(filename), "apache-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0, "%llu:%llu:%llu:%llu",
stats.total_accesses, stats.total_kbytes,
stats.busy_workers, stats.idle_workers);
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count < 2) {
log_print(LOG_ERROR, "p_apache: parse error");
return -1;
}
struct server_entry *entry = malloc(sizeof(struct server_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "p_apache: out of memory");
return -1;
}
entry->name = strdup(tokens->field[0]);
entry->handle = curl_easy_init();
if (entry->handle == NULL) {
free(entry);
return -1;
}
/* set URL */
int ret = curl_easy_setopt(entry->handle, CURLOPT_URL, tokens->field[1]);
if (ret != 0) {
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
curl_easy_cleanup(entry->handle);
free(entry);
return -1;
}
if (tokens->field[2] != NULL && tokens->field[3] != NULL) {
*(tokens->field[3] -1) = ':';
log_print(LOG_INFO, "p_apache: auth: '%s'", tokens->field[2]);
/* set username:password */
ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, tokens->field[2]);
if (ret != 0) {
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
curl_easy_cleanup(entry->handle);
free(entry);
return -1;
}
}
ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEFUNCTION, &curl_callback);
if (ret != 0) {
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
curl_easy_cleanup(entry->handle);
free(entry);
return -1;
}
ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEDATA, entry);
if (ret != 0) {
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
curl_easy_cleanup(entry->handle);
free(entry);
return -1;
}
log_print(LOG_INFO, "p_apache: added server '%s'", entry->name);
list_add_tail(&entry->list, &server_list);
return 0;
}
static int init(void)
{
rxbuf = lbuf_create(BUFSIZE);
if (rxbuf == NULL) {
log_print(LOG_ERROR, "p_apache: out of memory");
return -1;
}
config_get_strtokens("p_apache", "server", ",", 4, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct server_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &server_list, list) {
curl_easy_cleanup(entry->handle);
free(entry->name);
free(entry);
}
lbuf_free(rxbuf);
return 0;
}
struct sammler_plugin plugin = {
.name = "apache",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,176 +0,0 @@
/***************************************************************************
* Copyright (C) 04/2007 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define DS_L3PROTO 1
#define DS_L4PROTO 2
#define DS_TCP 3
struct sammler_plugin plugin;
static struct nfct_handle *cth;
struct ct_values {
int total;
int local;
int nated;
int unreplied;
int proto_tcp;
int proto_udp;
int proto_unknown;
int tcp_state[10];
};
static const char *l3proto_ds_def = {
"DS:total:GAUGE:15:0:U "
"DS:local:GAUGE:15:0:U "
"DS:nated:GAUGE:15:0:U "
"DS:unreplied:GAUGE:15:0:U "
};
static const char *l4proto_ds_def = {
"DS:tcp:GAUGE:15:0:U "
"DS:udp:GAUGE:15:0:U "
"DS:unknown:GAUGE:15:0:U "
};
static const char *tcp_ds_def = {
"DS:none:GAUGE:15:0:U "
"DS:syn_sent:GAUGE:15:0:U "
"DS:syn_recv:GAUGE:15:0:U "
"DS:established:GAUGE:15:0:U "
"DS:fin_wait:GAUGE:15:0:U "
"DS:close_wait:GAUGE:15:0:U "
"DS:last_ack:GAUGE:15:0:U "
"DS:time_wait:GAUGE:15:0:U "
"DS:close:GAUGE:15:0:U "
"DS:listen:GAUGE:15:0:U "
};
static const char * get_ds(int ds_id)
{
switch (ds_id) {
case DS_L3PROTO:
return l3proto_ds_def;
case DS_L4PROTO:
return l4proto_ds_def;
case DS_TCP:
return tcp_ds_def;
default:
return NULL;
}
}
static int probe_cb(void *arg, unsigned int flags, int type, void *privdata)
{
struct nfct_conntrack *ct = (struct nfct_conntrack *)arg;
struct ct_values *data = (struct ct_values *)privdata;
data->total++;
if (ct->status & IPS_NAT_MASK)
data->nated++;
else
data->local++;
if (!(ct->status & IPS_SEEN_REPLY))
data->unreplied++;
switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
case IPPROTO_TCP:
data->proto_tcp++;
data->tcp_state[ct->protoinfo.tcp.state]++;
break;
case IPPROTO_UDP:
data->proto_udp++;
break;
default:
data->proto_unknown++;
break;
}
return 0;
}
static int probe(void)
{
struct ct_values data;
memset(&data, 0, sizeof(data));
nfct_register_callback(cth, probe_cb, &data);
if (nfct_dump_conntrack_table(cth, AF_INET) < 0) {
log_print(LOG_WARN, "plugin conntrack: nfct_dump_conntrack_table()");
return -1;
}
probe_submit(&plugin, "conntrack.rrd", DS_L3PROTO, "%d:%d:%d:%d",
data.total, data.local, data.nated, data.unreplied);
probe_submit(&plugin, "conntrack-proto.rrd", DS_L4PROTO, "%d:%d:%d",
data.proto_tcp, data.proto_udp, data.proto_unknown);
probe_submit(&plugin, "conntrack-tcp.rrd", DS_TCP, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
data.tcp_state[0], data.tcp_state[1], data.tcp_state[2], data.tcp_state[3],
data.tcp_state[4], data.tcp_state[5], data.tcp_state[6], data.tcp_state[7],
data.tcp_state[8], data.tcp_state[9]);
return 0;
}
static int init(void)
{
cth = nfct_open(CONNTRACK, 0);
if (cth == NULL) {
log_print(LOG_WARN, "plugin conntrack: nfct_open()");
return -1;
}
return 0;
}
static int fini(void)
{
nfct_close(cth);
return 0;
}
struct sammler_plugin plugin = {
.name = "conntrack",
.interval = 10,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,152 +0,0 @@
/***************************************************************************
* Copyright (C) 06/2010 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "configfile.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#include "sgio.h"
int verbose = 0;
int prefer_ata12 = 0;
struct sammler_plugin plugin;
struct device_entry {
struct list_head list;
char *devpath;
};
static LIST_HEAD(device_list);
static const char *ds_def = {
"DS:active:GAUGE:90:0:1 "
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
struct device_entry *entry;
list_for_each_entry(entry, &device_list, list) {
int fd = open(entry->devpath, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
log_print(LOG_ERROR, "%s: failed to open %s", plugin.name, entry->devpath);
continue;
}
uint8_t args[4] = { ATA_OP_CHECKPOWERMODE1, 0, 0, 0 };
if (do_drive_cmd(fd, args)) {
args[0] = ATA_OP_CHECKPOWERMODE2;
if (do_drive_cmd(fd, args)) {
log_print(LOG_ERROR, "%s: failed to query %s", plugin.name, entry->devpath);
close(fd);
continue;
}
}
/*
switch (args[2]) {
case 0x00: state = "standby"; break;
case 0x40: state = "NVcache_spindown"; break;
case 0x41: state = "NVcache_spinup"; break;
case 0x80: state = "idle"; break;
case 0xff: state = "active/idle"; break;
default: state = "unknown"; break;
}
*/
char *dev = strrchr(entry->devpath, '/');
if (dev == NULL) {
dev = entry->devpath;
} else {
dev++;
}
char filename[32];
int len = snprintf(filename, sizeof(filename), "diskstandby-%s.rrd", dev);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0, "%u", (args[2] == 0xff) ? 1 : 0);
close(fd);
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count != 1) {
log_print(LOG_ERROR, "%s: parse error", plugin.name);
return -1;
}
struct device_entry *entry = malloc(sizeof(struct device_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
return -1;
}
entry->devpath = strdup(tokens->field[0]);
log_print(LOG_INFO, "%s: added device '%s'", plugin.name, entry->devpath);
list_add_tail(&entry->list, &device_list);
return 0;
}
static int init(void)
{
config_get_strtokens("p_diskstandby", "device", ",", 1, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct device_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &device_list, list) {
free(entry->devpath);
free(entry);
}
return 0;
}
struct sammler_plugin plugin = {
.name = "diskstandby",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,102 +0,0 @@
/***************************************************************************
* Copyright (C) 04/2007 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#define BUFSIZE 1024
struct sammler_plugin plugin;
static char *buffer;
static const char *ds_def = {
"DS:read_cnt:COUNTER:15:0:U "
"DS:read_sec:COUNTER:15:0:U "
"DS:read_ms:COUNTER:15:0:U "
"DS:write_cnt:COUNTER:15:0:U "
"DS:write_sec:COUNTER:15:0:U "
"DS:write_ms:COUNTER:15:0:U "
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
FILE *fp = fopen("/proc/diskstats", "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin diskstats: fopen()");
return -1;
}
while (fgets(buffer, BUFSIZE, fp) != NULL) {
int major, minor;
char device[16];
unsigned int val[11];
int cnt = sscanf(buffer, "%d %d %s %u %u %u %u %u %u %u %u %u %u %u",
&major, &minor, device, &val[0],
&val[1], &val[2], &val[3], &val[4],
&val[5], &val[6], &val[7], &val[8],
&val[9], &val[10]);
if (cnt != 14 || val[0] == 0 || val[1] == 0)
continue;
char filename[32];
int len = snprintf(filename, sizeof(filename), "disk-%s.rrd", device);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0,
"%u:%u:%u:%u:%u:%u",
val[0], val[2], val[3],
val[4], val[6], val[7]);
}
fclose(fp);
return 0;
}
static int init(void)
{
buffer = malloc(BUFSIZE);
return (buffer == NULL) ? -1 : 0;
}
static int fini(void)
{
free(buffer);
return 0;
}
struct sammler_plugin plugin = {
.name = "diskstat",
.interval = 10,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,212 +0,0 @@
/***************************************************************************
* Copyright (C) 12/2012 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "configfile.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#include "sockaddr.h"
#define RESP_SIZE 1024
struct sammler_plugin plugin;
struct server_entry {
struct list_head list;
char *name;
int errors;
struct sockaddr_in sa;
};
static LIST_HEAD(server_list);
static char *resp_buf;
static const char *ds_def = {
"DS:temperature:GAUGE:90:0:100"
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
struct server_entry *entry;
list_for_each_entry(entry, &server_list, list) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
log_print(LOG_WARN, "%s: socket()", plugin.name);
continue;
}
int ret = connect(sock, (struct sockaddr *)&entry->sa, sizeof(entry->sa));
if (ret != 0) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "%s: connect(%s)", plugin.name, get_sockaddr_buf(&entry->sa));
close(sock);
continue;
}
int pos = 0;
int len;
do {
len = read(sock, resp_buf + pos, RESP_SIZE - pos);
if ((pos == 0) && (len <= 0)) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "%s: read()", plugin.name);
break;
}
pos += len;
} while (len > 0);
close(sock);
if (pos == 0)
continue;
resp_buf[pos] = '\0';
/* '|/dev/sda|OCZ-VERTEX3|128|C||/dev/sdb|HDT722525DLA380|SLP|*||/dev/sdc|Generic STORAGE DEVICE|NA|*|' */
char *tok, *tmp = NULL, *resp = resp_buf;
int i = 0;
char *device = NULL;
int temperature = 0;
while ((tok = strtok_r(resp, "|", &tmp)) != NULL) {
if ((i % 4) == 0) {
device = strrchr(tok, '/');
if (device != NULL && *(device +1) == '\0')
device = NULL;
else
device++;
} else if ((i % 4) == 2) {
char *tmp2;
temperature = strtol(tok, &tmp2, 10);
if (*tmp2 != '\0')
device = NULL;
} else if ((i % 4) == 3) {
if ((tok[0] == 'C') && (device != NULL)) {
char filename[32];
len = snprintf(filename, sizeof(filename), "%s-%s.rrd", plugin.name, device);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0, "%d", temperature);
}
device = NULL;
temperature = 0;
}
i++;
resp = NULL;
}
if (entry->errors > 0) {
log_print(LOG_ERROR, "%s: success (%s) after %d errors",
plugin.name, entry->name, entry->errors);
entry->errors = 0;
}
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count != 2) {
log_print(LOG_ERROR, "%s: parse error", plugin.name);
return -1;
}
struct server_entry *entry = malloc(sizeof(struct server_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
return -1;
}
entry->name = strdup(tokens->field[0]);
entry->errors = 0;
if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) {
log_print(LOG_ERROR, "%s: invalid address: <%s>", plugin.name, tokens->field[1]);
free(entry->name);
free(entry);
return -1;
}
log_print(LOG_INFO, "%s: added server '%s'", plugin.name, entry->name);
list_add_tail(&entry->list, &server_list);
return 0;
}
static int init(void)
{
resp_buf = malloc(RESP_SIZE);
if (resp_buf == NULL) {
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
return -1;
}
config_get_strtokens("p_hddtemp", "server", ",", 2, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct server_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &server_list, list) {
free(entry->name);
free(entry);
}
free(resp_buf);
return 0;
}
struct sammler_plugin plugin = {
.name = "hddtemp",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,125 +0,0 @@
/***************************************************************************
* Copyright (C) 10/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "configfile.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
struct sammler_plugin plugin;
struct hwmon_entry {
struct list_head list;
char *name;
char *path;
};
static LIST_HEAD(hwmon_list);
static const char *ds_def = {
"DS:temp:GAUGE:15:0:U "
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
struct hwmon_entry *entry;
list_for_each_entry(entry, &hwmon_list, list) {
FILE *fp = fopen(entry->path, "r");
if (fp == NULL) {
log_print(LOG_WARN, "plugin hwmon: fopen(%s)", entry->path);
continue;
}
int temp;
if (fscanf(fp, "%d\n", &temp) != 1) {
log_print(LOG_WARN, "plugin hwmon: fscanf()");
fclose(fp);
continue;
}
fclose(fp);
char filename[32];
int len = snprintf(filename, sizeof(filename), "hwmon-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0, "%d", temp);
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count != 2) {
log_print(LOG_ERROR, "p_hwmon: parse error");
return -1;
}
struct hwmon_entry *entry = malloc(sizeof(struct hwmon_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "p_hwmon: out of memory");
return -1;
}
entry->name = strdup(tokens->field[0]);
entry->path = strdup(tokens->field[1]);
log_print(LOG_DEBUG, "p_hwmon: added sensor '%s' (%s)", entry->name, entry->path);
list_add_tail(&entry->list, &hwmon_list);
return 0;
}
static int init(void)
{
config_get_strtokens("p_hwmon", "temp", ",", 2, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct hwmon_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &hwmon_list, list) {
free(entry->name);
free(entry->path);
free(entry);
}
return 0;
}
struct sammler_plugin plugin = {
.name = "hwmon",
.interval = 10,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,204 +0,0 @@
/***************************************************************************
* Copyright (C) 10/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "configfile.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#include "mysql_helper.h"
#define DS_TRAFFIC 1
#define DS_COMMANDS 2
#define DS_QCACHE 3
#define DS_THREADS 4
struct sammler_plugin plugin;
struct server_entry {
struct list_head list;
void *mysql;
char *name;
};
static LIST_HEAD(server_list);
static const char *traffic_ds_def = {
"DS:bytes_received:COUNTER:90:0:U "
"DS:bytes_sent:COUNTER:90:0:U "
};
static const char *commands_ds_def = {
"DS:com_delete:COUNTER:90:0:U "
"DS:com_insert:COUNTER:90:0:U "
"DS:com_select:COUNTER:90:0:U "
"DS:com_update:COUNTER:90:0:U "
"DS:connections:COUNTER:90:0:U "
"DS:questions:COUNTER:90:0:U "
};
static const char *qcache_ds_def = {
"DS:qc_free_blocks:GAUGE:90:0:U "
"DS:qc_free_memory:GAUGE:90:0:U "
"DS:qc_hits:COUNTER:90:0:U "
"DS:qc_inserts:COUNTER:90:0:U "
"DS:qc_lowmem_prunes:COUNTER:90:0:U "
"DS:qc_not_cached:COUNTER:90:0:U "
"DS:qc_queries_in_cache:GAUGE:90:0:U "
"DS:qc_total_blocks:GAUGE:90:0:U "
};
static const char *threads_ds_def = {
"DS:threads_cached:GAUGE:90:0:U "
"DS:threads_connected:GAUGE:90:0:U "
"DS:threads_created:COUNTER:90:0:U "
"DS:threads_running:GAUGE:90:0:U "
};
static const char * get_ds(int ds_id)
{
switch (ds_id) {
case DS_TRAFFIC:
return traffic_ds_def;
case DS_COMMANDS:
return commands_ds_def;
case DS_QCACHE:
return qcache_ds_def;
case DS_THREADS:
return threads_ds_def;
default:
return NULL;
}
}
static int probe(void)
{
struct mysql_stats stats;
char filename[32];
int len;
memset(&stats, 0, sizeof(struct mysql_stats));
struct server_entry *entry;
list_for_each_entry(entry, &server_list, list) {
if (ping_connection(entry->mysql) != 0)
continue;
if (get_stats(entry->mysql, &stats) != 0)
continue;
len = snprintf(filename, sizeof(filename), "mysql-traffic-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_TRAFFIC, "%llu:%llu",
stats.bytes_received, stats.bytes_sent);
len = snprintf(filename, sizeof(filename), "mysql-commands-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_COMMANDS, "%llu:%llu:%llu:%llu:%llu:%llu",
stats.com_delete, stats.com_insert,
stats.com_select, stats.com_update,
stats.connections, stats.questions);
len = snprintf(filename, sizeof(filename), "mysql-qcache-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_QCACHE, "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
stats.qc_free_blocks, stats.qc_free_memory,
stats.qc_hits, stats.qc_inserts,
stats.qc_lowmem_prunes, stats.qc_not_cached,
stats.qc_queries_in_cache, stats.qc_total_blocks);
len = snprintf(filename, sizeof(filename), "mysql-threads-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, DS_THREADS, "%llu:%llu:%llu:%llu",
stats.threads_cached, stats.threads_connected,
stats.threads_created, stats.threads_running);
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count != 4) {
log_print(LOG_ERROR, "p_mysql: parse error");
return -1;
}
void *mysql = init_connection(tokens->field[1], tokens->field[2], tokens->field[3]);
if (mysql == NULL) {
return -1;
}
struct server_entry *entry = malloc(sizeof(struct server_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "p_mysql: out of memory");
close_connection(mysql);
return -1;
}
entry->name = strdup(tokens->field[0]);
entry->mysql = mysql;
log_print(LOG_DEBUG, "p_mysql: added server '%s'", entry->name);
list_add_tail(&entry->list, &server_list);
return 0;
}
static int init(void)
{
config_get_strtokens("p_mysql", "server", ",", 4, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct server_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &server_list, list) {
close_connection(entry->mysql);
free(entry->name);
free(entry);
}
return 0;
}
struct sammler_plugin plugin = {
.name = "mysql",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

View File

@ -1,141 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
#include "logging.h"
#include "mysql_helper.h"
void * init_connection(const char *host, const char *user, const char *pass)
{
MYSQL *con = NULL;
con = mysql_init(con);
if (con == NULL)
return NULL;
con = mysql_real_connect(con, host, user, pass, NULL, 0, NULL, 0);
if (con == NULL) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return NULL;
}
return con;
}
int ping_connection(void *mysql)
{
MYSQL *con = mysql;
return mysql_ping(con);
}
int close_connection(void *mysql)
{
MYSQL *con = mysql;
mysql_close(con);
return 0;
}
int get_stats(void *mysql, struct mysql_stats *stats)
{
MYSQL *con = mysql;
char *query;
if (mysql_get_server_version(con) >= 50002)
query = "SHOW GLOBAL STATUS";
else
query = "SHOW STATUS";
if (mysql_real_query(con, query, strlen(query))) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return -1;
}
MYSQL_RES *res;
res = mysql_store_result(con);
if (res == NULL) {
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
return -1;
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
char *key;
unsigned long long val;
key = row[0];
val = atoll(row[1]);
if (!strncmp(key, "Bytes_", 6)) {
if (!strcmp(key +6, "received"))
stats->bytes_received = val;
else if (!strcmp(key +6, "sent"))
stats->bytes_sent = val;
} else if (!strncmp(key, "Com_", 4)) {
if (!strcmp(key +4, "delete"))
stats->com_delete = val;
else if (!strcmp(key +4, "insert"))
stats->com_insert = val;
else if (!strcmp(key +4, "select"))
stats->com_select = val;
else if (!strcmp(key +4, "update"))
stats->com_update = val;
} else if (!strcmp(key, "Connections")) {
stats->connections = val;
} else if (!strncmp(key, "Qcache_", 7)) {
if (!strcmp(key +7, "free_blocks"))
stats->qc_free_blocks = val;
else if (!strcmp(key +7, "free_memory"))
stats->qc_free_memory = val;
else if (!strcmp(key +7, "hits"))
stats->qc_hits = val;
else if (!strcmp(key +7, "inserts"))
stats->qc_inserts = val;
else if (!strcmp(key +7, "lowmem_prunes"))
stats->qc_lowmem_prunes = val;
else if (!strcmp(key +7, "not_cached"))
stats->qc_not_cached = val;
else if (!strcmp(key +7, "queries_in_cache"))
stats->qc_queries_in_cache = val;
else if (!strcmp(key +7, "total_blocks"))
stats->qc_total_blocks = val;
} else if (!strcmp(key, "Questions")) {
stats->questions = val;
} else if (!strncmp(key, "Threads_", 8)) {
if (!strcmp(key, "Threads_cached"))
stats->threads_cached = val;
else if (!strcmp(key, "Threads_connected"))
stats->threads_connected = val;
else if (!strcmp(key, "Threads_created"))
stats->threads_created = val;
else if (!strcmp(key, "Threads_running"))
stats->threads_running = val;
}
}
mysql_free_result(res);
return 0;
}

View File

@ -1,35 +0,0 @@
#ifndef _MYSQL_HELPER_H_
#define _MYSQL_HELPER_H_
#include <stdint.h>
struct mysql_stats {
uint64_t bytes_received;
uint64_t bytes_sent;
uint64_t com_delete;
uint64_t com_insert;
uint64_t com_select;
uint64_t com_update;
uint64_t connections;
uint64_t qc_free_blocks;
uint64_t qc_free_memory;
uint64_t qc_hits;
uint64_t qc_inserts;
uint64_t qc_lowmem_prunes;
uint64_t qc_not_cached;
uint64_t qc_queries_in_cache;
uint64_t qc_total_blocks;
uint64_t questions;
uint64_t threads_cached;
uint64_t threads_connected;
uint64_t threads_created;
uint64_t threads_running;
};
void * init_connection(const char *host, const char *user, const char *pass);
int ping_connection(void *mysql);
int close_connection(void *mysql);
int get_stats(void *mysql, struct mysql_stats *stats);
#endif /* _MYSQL_HELPER_H_ */

View File

@ -1,492 +0,0 @@
/* sgio.c - by Mark Lord (C) 2007 -- freely distributable */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include "sgio.h"
//#include "hdparm.h"
#include <linux/hdreg.h>
extern int verbose;
extern int prefer_ata12;
/*
* Taskfile layout for SG_ATA_16 cdb:
*
* LBA48:
* cdb[ 3] = hob_feat
* cdb[ 5] = hob_nsect
* cdb[ 7] = hob_lbal
* cdb[ 9] = hob_lbam
* cdb[11] = hob_lbah
*
* LBA28/LBA48:
* cdb[ 4] = feat
* cdb[ 6] = nsect
* cdb[ 8] = lbal
* cdb[10] = lbam
* cdb[12] = lbah
* cdb[13] = device
* cdb[14] = command
*
* Taskfile layout for SG_ATA_12 cdb:
*
* cdb[ 3] = feat
* cdb[ 4] = nsect
* cdb[ 5] = lbal
* cdb[ 6] = lbam
* cdb[ 7] = lbah
* cdb[ 8] = device
* cdb[ 9] = command
*
* dxfer_direction choices:
* SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV, SG_DXFER_NONE
*/
static inline int needs_lba48 (__u8 ata_op, __u64 lba, unsigned int nsect)
{
const __u64 lba28_limit = (1<<28) - 1;
switch (ata_op) {
case ATA_OP_READ_PIO_EXT:
case ATA_OP_READ_DMA_EXT:
case ATA_OP_WRITE_PIO_EXT:
case ATA_OP_WRITE_DMA_EXT:
case ATA_OP_READ_VERIFY_EXT:
case ATA_OP_WRITE_UNC_EXT:
case ATA_OP_READ_NATIVE_MAX_EXT:
case ATA_OP_SET_MAX_EXT:
case ATA_OP_FLUSHCACHE_EXT:
return 1;
}
if (lba >= lba28_limit)
return 1;
if (nsect) {
if (nsect > 0xff)
return 1;
if ((lba + nsect - 1) >= lba28_limit)
return 1;
}
return 0;
}
void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect)
{
memset(tf, 0, sizeof(*tf));
tf->command = ata_op;
tf->dev = ATA_USING_LBA;
tf->lob.lbal = lba;
tf->lob.lbam = lba >> 8;
tf->lob.lbah = lba >> 16;
tf->lob.nsect = nsect;
if (needs_lba48(ata_op, lba, nsect)) {
tf->is_lba48 = 1;
tf->hob.nsect = nsect >> 8;
tf->hob.lbal = lba >> 24;
tf->hob.lbam = lba >> 32;
tf->hob.lbah = lba >> 40;
} else {
tf->dev |= (lba >> 24) & 0x0f;
}
}
#ifdef SG_IO
__u64 tf_to_lba (struct ata_tf *tf)
{
__u32 lba24, lbah;
__u64 lba64;
lba24 = (tf->lob.lbah << 16) | (tf->lob.lbam << 8) | (tf->lob.lbal);
if (tf->is_lba48)
lbah = (tf->hob.lbah << 16) | (tf->hob.lbam << 8) | (tf->hob.lbal);
else
lbah = (tf->dev & 0x0f);
lba64 = (((__u64)lbah) << 24) | (__u64)lba24;
return lba64;
}
enum {
SG_CDB2_TLEN_NODATA = 0 << 0,
SG_CDB2_TLEN_FEAT = 1 << 0,
SG_CDB2_TLEN_NSECT = 2 << 0,
SG_CDB2_TLEN_BYTES = 0 << 2,
SG_CDB2_TLEN_SECTORS = 1 << 2,
SG_CDB2_TDIR_TO_DEV = 0 << 3,
SG_CDB2_TDIR_FROM_DEV = 1 << 3,
SG_CDB2_CHECK_COND = 1 << 5,
};
static void dump_bytes (const char *prefix, unsigned char *p, int len)
{
int i;
if (prefix)
fprintf(stderr, "%s: ", prefix);
for (i = 0; i < len; ++i)
fprintf(stderr, " %02x", p[i]);
fprintf(stderr, "\n");
}
int sg16 (int fd, int rw, int dma, struct ata_tf *tf,
void *data, unsigned int data_bytes, unsigned int timeout_secs)
{
unsigned char cdb[SG_ATA_16_LEN];
unsigned char sb[32], *desc;
struct scsi_sg_io_hdr io_hdr;
memset(&cdb, 0, sizeof(cdb));
memset(&sb, 0, sizeof(sb));
memset(&io_hdr, 0, sizeof(struct scsi_sg_io_hdr));
if (dma) {
//cdb[1] = data ? (rw ? SG_ATA_PROTO_UDMA_OUT : SG_ATA_PROTO_UDMA_IN) : SG_ATA_PROTO_NON_DATA;
cdb[1] = data ? SG_ATA_PROTO_DMA : SG_ATA_PROTO_NON_DATA;
} else {
cdb[1] = data ? (rw ? SG_ATA_PROTO_PIO_OUT : SG_ATA_PROTO_PIO_IN) : SG_ATA_PROTO_NON_DATA;
}
cdb[ 2] = SG_CDB2_CHECK_COND;
if (data) {
cdb[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS;
cdb[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV;
}
if (!prefer_ata12 || tf->is_lba48) {
cdb[ 0] = SG_ATA_16;
cdb[ 4] = tf->lob.feat;
cdb[ 6] = tf->lob.nsect;
cdb[ 8] = tf->lob.lbal;
cdb[10] = tf->lob.lbam;
cdb[12] = tf->lob.lbah;
cdb[13] = tf->dev;
cdb[14] = tf->command;
if (tf->is_lba48) {
cdb[ 1] |= SG_ATA_LBA48;
cdb[ 3] = tf->hob.feat;
cdb[ 5] = tf->hob.nsect;
cdb[ 7] = tf->hob.lbal;
cdb[ 9] = tf->hob.lbam;
cdb[11] = tf->hob.lbah;
}
io_hdr.cmd_len = SG_ATA_16_LEN;
} else {
cdb[ 0] = SG_ATA_12;
cdb[ 3] = tf->lob.feat;
cdb[ 4] = tf->lob.nsect;
cdb[ 5] = tf->lob.lbal;
cdb[ 6] = tf->lob.lbam;
cdb[ 7] = tf->lob.lbah;
cdb[ 8] = tf->dev;
cdb[ 9] = tf->command;
io_hdr.cmd_len = SG_ATA_12_LEN;
}
io_hdr.interface_id = 'S';
io_hdr.mx_sb_len = sizeof(sb);
io_hdr.dxfer_direction = data ? (rw ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV) : SG_DXFER_NONE;
io_hdr.dxfer_len = data ? data_bytes : 0;
io_hdr.dxferp = data;
io_hdr.cmdp = cdb;
io_hdr.sbp = sb;
io_hdr.pack_id = tf_to_lba(tf);
io_hdr.timeout = (timeout_secs ? timeout_secs : 5) * 1000; /* msecs */
if (verbose)
dump_bytes("outgoing cdb", cdb, sizeof(cdb));
if (ioctl(fd, SG_IO, &io_hdr) == -1) {
if (verbose)
perror("ioctl(fd,SG_IO)");
return -1; /* SG_IO not supported */
}
if (verbose)
fprintf(stderr, "SG_IO: ATA_%u status=0x%x, host_status=0x%x, driver_status=0x%x\n",
io_hdr.cmd_len, io_hdr.status, io_hdr.host_status, io_hdr.driver_status);
if (io_hdr.host_status || io_hdr.driver_status != SG_DRIVER_SENSE
|| (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION))
{
if (verbose)
fprintf(stderr, "SG_IO: bad response (not CHECK_CONDITION)\n");
errno = EBADE;
return -1;
}
desc = sb + 8;
if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) {
if (verbose)
dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb));
errno = EBADE;
return -1;
}
if (verbose)
dump_bytes("SG_IO: sb[]", sb, sizeof(sb));
if (verbose) {
int len = desc[1], maxlen = sizeof(sb) - 8 - 2;
if (len > maxlen)
len = maxlen;
dump_bytes("SG_IO: desc[]", desc, len);
}
tf->is_lba48 = desc[ 2] & 1;
tf->error = desc[ 3];
tf->lob.nsect = desc[ 5];
tf->lob.lbal = desc[ 7];
tf->lob.lbam = desc[ 9];
tf->lob.lbah = desc[11];
tf->dev = desc[12];
tf->status = desc[13];
tf->hob.feat = 0;
if (tf->is_lba48) {
tf->hob.nsect = desc[ 4];
tf->hob.lbal = desc[ 6];
tf->hob.lbam = desc[ 8];
tf->hob.lbah = desc[10];
} else {
tf->hob.nsect = 0;
tf->hob.lbal = 0;
tf->hob.lbam = 0;
tf->hob.lbah = 0;
}
if (verbose)
fprintf(stderr, " ATA_%u stat=%02x err=%02x nsect=%02x lbal=%02x lbam=%02x lbah=%02x dev=%02x\n",
io_hdr.cmd_len, tf->status, tf->error, tf->lob.nsect, tf->lob.lbal, tf->lob.lbam, tf->lob.lbah, tf->dev);
if (tf->status & (ATA_STAT_ERR | ATA_STAT_DRQ)) {
if (verbose) {
fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n",
tf->command, tf->status, tf->error);
}
errno = EIO;
return -1;
}
return 0;
}
#endif /* SG_IO */
int do_drive_cmd (int fd, unsigned char *args)
{
#ifdef SG_IO
struct ata_tf tf;
void *data = NULL;
unsigned int data_bytes = 0;
int rc;
if (args == NULL)
goto use_legacy_ioctl;
/*
* Reformat and try to issue via SG_IO:
*/
if (args[3]) {
data_bytes = args[3] * 512;
data = args + 4;
}
tf_init(&tf, args[0], 0, args[1]);
tf.lob.feat = args[2];
if (tf.command == ATA_OP_SMART) {
tf.lob.nsect = args[3];
tf.lob.lbal = args[1];
tf.lob.lbam = 0x4f;
tf.lob.lbah = 0xc2;
}
rc = sg16(fd, SG_READ, SG_PIO, &tf, data, data_bytes, 0);
if (rc == -1) {
if (errno == EINVAL || errno == ENODEV)
goto use_legacy_ioctl;
}
if (rc == 0 || errno == EIO) {
args[0] = tf.status;
args[1] = tf.error;
args[2] = tf.lob.nsect;
}
return rc;
use_legacy_ioctl:
#endif /* SG_IO */
if (verbose)
fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n");
return ioctl(fd, HDIO_DRIVE_CMD, args);
}
int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs)
{
int rc;
#ifdef SG_IO
struct ata_tf tf;
void *data = NULL;
unsigned int data_bytes = 0;
int rw = SG_READ;
/*
* Reformat and try to issue via SG_IO:
*/
tf_init(&tf, 0, 0, 0);
#if 1 /* debugging */
if (verbose) {
printf("oflags.lob_all=0x%02x, flags={", r->oflags.lob_all);
if (r->oflags.lob.feat) printf(" feat");
if (r->oflags.lob.lbal) printf(" lbal");
if (r->oflags.lob.nsect)printf(" nsect");
if (r->oflags.lob.lbam) printf(" lbam");
if (r->oflags.lob.lbah) printf(" lbah");
if (r->oflags.lob.dev) printf(" dev");
if (r->oflags.lob.command) printf(" command");
printf(" }\n");
printf("oflags.hob_all=0x%02x, flags={", r->oflags.hob_all);
if (r->oflags.hob.feat) printf(" feat");
if (r->oflags.hob.lbal) printf(" lbal");
if (r->oflags.hob.nsect)printf(" nsect");
if (r->oflags.hob.lbam) printf(" lbam");
if (r->oflags.hob.lbah) printf(" lbah");
printf(" }\n");
}
#endif
if (r->oflags.lob.feat) tf.lob.feat = r->lob.feat;
if (r->oflags.lob.lbal) tf.lob.lbal = r->lob.lbal;
if (r->oflags.lob.nsect) tf.lob.nsect = r->lob.nsect;
if (r->oflags.lob.lbam) tf.lob.lbam = r->lob.lbam;
if (r->oflags.lob.lbah) tf.lob.lbah = r->lob.lbah;
if (r->oflags.lob.dev) tf.dev = r->lob.dev;
if (r->oflags.lob.command) tf.command = r->lob.command;
if (r->oflags.hob_all || r->iflags.hob_all) {
tf.is_lba48 = 1;
if (r->oflags.hob.feat) tf.hob.feat = r->hob.feat;
if (r->oflags.hob.lbal) tf.hob.lbal = r->hob.lbal;
if (r->oflags.hob.nsect)tf.hob.nsect = r->hob.nsect;
if (r->oflags.hob.lbam) tf.hob.lbam = r->hob.lbam;
if (r->oflags.hob.lbah) tf.hob.lbah = r->hob.lbah;
if (verbose)
fprintf(stderr, "using LBA48 taskfile\n");
}
switch (r->cmd_req) {
case TASKFILE_CMD_REQ_OUT:
case TASKFILE_CMD_REQ_RAW_OUT:
data_bytes = r->obytes;
data = r->data;
rw = SG_WRITE;
break;
case TASKFILE_CMD_REQ_IN:
data_bytes = r->ibytes;
data = r->data;
break;
}
rc = sg16(fd, rw, SG_PIO, &tf, data, data_bytes, timeout_secs);
if (rc == -1) {
if (errno == EINVAL || errno == ENODEV)
goto use_legacy_ioctl;
}
if (rc == 0 || errno == EIO) {
if (r->iflags.lob.feat) r->lob.feat = tf.error;
if (r->iflags.lob.lbal) r->lob.lbal = tf.lob.lbal;
if (r->iflags.lob.nsect) r->lob.nsect = tf.lob.nsect;
if (r->iflags.lob.lbam) r->lob.lbam = tf.lob.lbam;
if (r->iflags.lob.lbah) r->lob.lbah = tf.lob.lbah;
if (r->iflags.lob.dev) r->lob.dev = tf.dev;
if (r->iflags.lob.command) r->lob.command = tf.status;
if (r->iflags.hob.feat) r->hob.feat = tf.hob.feat;
if (r->iflags.hob.lbal) r->hob.lbal = tf.hob.lbal;
if (r->iflags.hob.nsect) r->hob.nsect = tf.hob.nsect;
if (r->iflags.hob.lbam) r->hob.lbam = tf.hob.lbam;
if (r->iflags.hob.lbah) r->hob.lbah = tf.hob.lbah;
}
return rc;
use_legacy_ioctl:
#else
timeout_secs = 0; /* keep compiler happy */
#endif /* SG_IO */
if (verbose)
fprintf(stderr, "trying legacy HDIO_DRIVE_TASKFILE\n");
errno = 0;
rc = ioctl(fd, HDIO_DRIVE_TASKFILE, r);
if (verbose) {
int err = errno;
fprintf(stderr, "rc=%d, errno=%d, returned ATA registers: ", rc, err);
if (r->iflags.lob.feat) fprintf(stderr, " er=%02x", r->lob.feat);
if (r->iflags.lob.nsect) fprintf(stderr, " ns=%02x", r->lob.nsect);
if (r->iflags.lob.lbal) fprintf(stderr, " ll=%02x", r->lob.lbal);
if (r->iflags.lob.lbam) fprintf(stderr, " lm=%02x", r->lob.lbam);
if (r->iflags.lob.lbah) fprintf(stderr, " lh=%02x", r->lob.lbah);
if (r->iflags.lob.dev) fprintf(stderr, " dh=%02x", r->lob.dev);
if (r->iflags.lob.command) fprintf(stderr, " st=%02x", r->lob.command);
if (r->iflags.hob.feat) fprintf(stderr, " err=%02x", r->hob.feat);
if (r->iflags.hob.nsect) fprintf(stderr, " err=%02x", r->hob.nsect);
if (r->iflags.hob.lbal) fprintf(stderr, " err=%02x", r->hob.lbal);
if (r->iflags.hob.lbam) fprintf(stderr, " err=%02x", r->hob.lbam);
if (r->iflags.hob.lbah) fprintf(stderr, " err=%02x", r->hob.lbah);
fprintf(stderr, "\n");
errno = err;
}
if (rc == -1 && errno == EINVAL) {
fprintf(stderr, "The running kernel lacks CONFIG_IDE_TASK_IOCTL support for this device.\n");
errno = EINVAL;
}
return rc;
}
void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48,
__u64 lba, unsigned int nsect, int data_bytes)
{
memset(r, 0, sizeof(struct hdio_taskfile) + data_bytes);
if (!data_bytes) {
r->dphase = TASKFILE_DPHASE_NONE;
r->cmd_req = TASKFILE_CMD_REQ_NODATA;
} else if (rw == RW_WRITE) {
r->dphase = TASKFILE_DPHASE_PIO_OUT;
r->cmd_req = TASKFILE_CMD_REQ_RAW_OUT;
r->obytes = data_bytes;
} else { /* rw == RW_READ */
r->dphase = TASKFILE_DPHASE_PIO_IN;
r->cmd_req = TASKFILE_CMD_REQ_IN;
r->ibytes = data_bytes;
}
r->lob.command = ata_op;
r->oflags.lob.command = 1;
r->oflags.lob.dev = 1;
r->oflags.lob.lbal = 1;
r->oflags.lob.lbam = 1;
r->oflags.lob.lbah = 1;
r->oflags.lob.nsect = 1;
r->iflags.lob.command = 1;
r->iflags.lob.feat = 1;
r->lob.nsect = nsect;
r->lob.lbal = lba;
r->lob.lbam = lba >> 8;
r->lob.lbah = lba >> 16;
r->lob.dev = 0xa0 | ATA_USING_LBA;
if (needs_lba48(ata_op, lba, nsect) || force_lba48) {
r->hob.nsect = nsect >> 8;
r->hob.lbal = lba >> 24;
r->hob.lbam = lba >> 32;
r->hob.lbah = lba >> 40;
r->oflags.hob.nsect = 1;
r->oflags.hob.lbal = 1;
r->oflags.hob.lbam = 1;
r->oflags.hob.lbah = 1;
} else {
r->lob.dev |= (lba >> 24) & 0x0f;
}
}

View File

@ -1,230 +0,0 @@
/* prototypes and stuff for ATA command ioctls */
#include <linux/types.h>
enum {
ATA_OP_READ_PIO = 0x20,
ATA_OP_READ_PIO_ONCE = 0x21,
ATA_OP_READ_LONG = 0x22,
ATA_OP_READ_LONG_ONCE = 0x23,
ATA_OP_READ_PIO_EXT = 0x24,
ATA_OP_READ_DMA_EXT = 0x25,
ATA_OP_READ_FPDMA = 0x60, // NCQ
ATA_OP_WRITE_PIO = 0x30,
ATA_OP_WRITE_LONG = 0x32,
ATA_OP_WRITE_LONG_ONCE = 0x33,
ATA_OP_WRITE_PIO_EXT = 0x34,
ATA_OP_WRITE_DMA_EXT = 0x35,
ATA_OP_WRITE_FPDMA = 0x61, // NCQ
ATA_OP_READ_VERIFY = 0x40,
ATA_OP_READ_VERIFY_ONCE = 0x41,
ATA_OP_READ_VERIFY_EXT = 0x42,
ATA_OP_WRITE_UNC_EXT = 0x45, // lba48, no data, uses feat reg
ATA_OP_FORMAT_TRACK = 0x50,
ATA_OP_DOWNLOAD_MICROCODE = 0x92,
ATA_OP_STANDBYNOW2 = 0x94,
ATA_OP_CHECKPOWERMODE2 = 0x98,
ATA_OP_SLEEPNOW2 = 0x99,
ATA_OP_PIDENTIFY = 0xa1,
ATA_OP_READ_NATIVE_MAX = 0xf8,
ATA_OP_READ_NATIVE_MAX_EXT = 0x27,
ATA_OP_SMART = 0xb0,
ATA_OP_DCO = 0xb1,
ATA_OP_ERASE_SECTORS = 0xc0,
ATA_OP_READ_DMA = 0xc8,
ATA_OP_WRITE_DMA = 0xca,
ATA_OP_DOORLOCK = 0xde,
ATA_OP_DOORUNLOCK = 0xdf,
ATA_OP_STANDBYNOW1 = 0xe0,
ATA_OP_IDLEIMMEDIATE = 0xe1,
ATA_OP_SETIDLE = 0xe3,
ATA_OP_SET_MAX = 0xf9,
ATA_OP_SET_MAX_EXT = 0x37,
ATA_OP_SET_MULTIPLE = 0xc6,
ATA_OP_CHECKPOWERMODE1 = 0xe5,
ATA_OP_SLEEPNOW1 = 0xe6,
ATA_OP_FLUSHCACHE = 0xe7,
ATA_OP_FLUSHCACHE_EXT = 0xea,
ATA_OP_IDENTIFY = 0xec,
ATA_OP_SETFEATURES = 0xef,
ATA_OP_SECURITY_SET_PASS = 0xf1,
ATA_OP_SECURITY_UNLOCK = 0xf2,
ATA_OP_SECURITY_ERASE_PREPARE = 0xf3,
ATA_OP_SECURITY_ERASE_UNIT = 0xf4,
ATA_OP_SECURITY_FREEZE_LOCK = 0xf5,
ATA_OP_SECURITY_DISABLE = 0xf6,
};
/*
* Some useful ATA register bits
*/
enum {
ATA_USING_LBA = (1 << 6),
ATA_STAT_DRQ = (1 << 3),
ATA_STAT_ERR = (1 << 0),
};
/*
* Useful parameters for init_hdio_taskfile():
*/
enum { RW_READ = 0,
RW_WRITE = 1,
LBA28_OK = 0,
LBA48_FORCE = 1,
};
/*
* Definitions and structures for use with SG_IO + ATA_16:
*/
struct ata_lba_regs {
__u8 feat;
__u8 nsect;
__u8 lbal;
__u8 lbam;
__u8 lbah;
};
struct ata_tf {
__u8 dev;
__u8 command;
__u8 error;
__u8 status;
__u8 is_lba48;
struct ata_lba_regs lob;
struct ata_lba_regs hob;
};
/*
* Definitions and structures for use with HDIO_DRIVE_TASKFILE:
*/
enum {
/*
* These (redundantly) specify the category of the request
*/
TASKFILE_CMD_REQ_NODATA = 0, /* ide: IDE_DRIVE_TASK_NO_DATA */
TASKFILE_CMD_REQ_IN = 2, /* ide: IDE_DRIVE_TASK_IN */
TASKFILE_CMD_REQ_OUT = 3, /* ide: IDE_DRIVE_TASK_OUT */
TASKFILE_CMD_REQ_RAW_OUT= 4, /* ide: IDE_DRIVE_TASK_RAW_WRITE */
/*
* These specify the method of transfer (pio, dma, multi, ..)
*/
TASKFILE_DPHASE_NONE = 0, /* ide: TASKFILE_IN */
TASKFILE_DPHASE_PIO_IN = 1, /* ide: TASKFILE_IN */
TASKFILE_DPHASE_PIO_OUT = 4, /* ide: TASKFILE_OUT */
};
struct reg_flags {
union {
unsigned lob_all : 8;
struct {
unsigned data : 1;
unsigned feat : 1;
unsigned lbal : 1;
unsigned nsect : 1;
unsigned lbam : 1;
unsigned lbah : 1;
unsigned dev : 1;
unsigned command : 1;
} lob;
};
union {
unsigned hob_all : 8;
struct {
unsigned data : 1;
unsigned feat : 1;
unsigned lbal : 1;
unsigned nsect : 1;
unsigned lbam : 1;
unsigned lbah : 1;
unsigned dev : 1;
unsigned command : 1;
} hob;
};
};
struct taskfile_regs {
__u8 data;
__u8 feat;
__u8 nsect;
__u8 lbal;
__u8 lbam;
__u8 lbah;
__u8 dev;
__u8 command;
};
struct hdio_taskfile {
struct taskfile_regs lob;
struct taskfile_regs hob;
struct reg_flags oflags;
struct reg_flags iflags;
int dphase;
int cmd_req; /* IDE command_type */
unsigned long obytes;
unsigned long ibytes;
__u16 data[0];
};
struct scsi_sg_io_hdr {
int interface_id;
int dxfer_direction;
unsigned char cmd_len;
unsigned char mx_sb_len;
unsigned short iovec_count;
unsigned int dxfer_len;
void * dxferp;
unsigned char * cmdp;
void * sbp;
unsigned int timeout;
unsigned int flags;
int pack_id;
void * usr_ptr;
unsigned char status;
unsigned char masked_status;
unsigned char msg_status;
unsigned char sb_len_wr;
unsigned short host_status;
unsigned short driver_status;
int resid;
unsigned int duration;
unsigned int info;
};
#ifndef SG_DXFER_NONE
#define SG_DXFER_NONE -1
#define SG_DXFER_TO_DEV -2
#define SG_DXFER_FROM_DEV -3
#define SG_DXFER_TO_FROM_DEV -4
#endif
#define SG_READ 0
#define SG_WRITE 1
#define SG_PIO 0
#define SG_DMA 1
#define SG_CHECK_CONDITION 0x02
#define SG_DRIVER_SENSE 0x08
#define SG_ATA_16 0x85
#define SG_ATA_16_LEN 16
#define SG_ATA_12 0xa1
#define SG_ATA_12_LEN 12
#define SG_ATA_LBA48 1
#define SG_ATA_PROTO_NON_DATA ( 3 << 1)
#define SG_ATA_PROTO_PIO_IN ( 4 << 1)
#define SG_ATA_PROTO_PIO_OUT ( 5 << 1)
#define SG_ATA_PROTO_DMA ( 6 << 1)
#define SG_ATA_PROTO_UDMA_IN (11 << 1) /* not yet supported in libata */
#define SG_ATA_PROTO_UDMA_OUT (12 << 1) /* not yet supported in libata */
void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect);
__u64 tf_to_lba (struct ata_tf *tf);
int sg16 (int fd, int rw, int dma, struct ata_tf *tf, void *data, unsigned int data_bytes, unsigned int timeout_secs);
int do_drive_cmd (int fd, unsigned char *args);
int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs);
int dev_has_sgio (int fd);
void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48,
__u64 lba, unsigned int nsect, int data_bytes);

View File

@ -1,213 +0,0 @@
/***************************************************************************
* Copyright (C) 02/2010 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "configfile.h"
#include "helper.h"
#include "list.h"
#include "logging.h"
#include "plugins.h"
#include "probe.h"
#include "sockaddr.h"
#define TS2_RESP_SIZE 1024
struct sammler_plugin plugin;
struct server_entry {
struct list_head list;
char *name;
int errors;
struct sockaddr_in sa;
};
static LIST_HEAD(server_list);
static char *ts2_resp_buf;
static const char *ds_def = {
"DS:users:GAUGE:90:0:U "
"DS:channels:GAUGE:90:0:U "
};
static const char * get_ds(int ds_id)
{
return ds_def;
}
static int probe(void)
{
struct server_entry *entry;
list_for_each_entry(entry, &server_list, list) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
log_print(LOG_WARN, "plugin ts2: socket()");
continue;
}
int ret = connect(sock, (struct sockaddr *)&entry->sa, sizeof(entry->sa));
if (ret != 0) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "plugin ts2: connect(%s)", get_sockaddr_buf(&entry->sa));
close(sock);
continue;
}
/* read prompt "[TS]" */
int len = read(sock, ts2_resp_buf, TS2_RESP_SIZE);
if (len <= 0) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "ts2: read(1)");
close(sock);
continue;
}
if (strncmp(ts2_resp_buf, "[TS]", 4) != 0) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "ts2: invalid prompt from server");
close(sock);
continue;
}
/* query "general informations" */
char cmd1[] = "gi\n";
write(sock, cmd1, sizeof(cmd1));
len = read(sock, ts2_resp_buf, TS2_RESP_SIZE);
if (len <= 0) {
if (entry->errors++ == 0)
log_print(LOG_ERROR, "ts2: read(2)");
close(sock);
continue;
}
/* send quit (but we close the socket anyway..) */
char cmd2[] = "quit";
write(sock, cmd2, sizeof(cmd2));
close(sock);
/* terminate response */
ts2_resp_buf[len] = '\0';
char *tok, *tmp, *resp = ts2_resp_buf;
int users = 0, channels = 0;
while ((tok = strtok_r(resp, "\r\n", &tmp)) != NULL) {
/* total_users_online=14 */
if (strncmp(tok, "total_users_online", 18) == 0) {
users = atoi(tok +19);
/* total_channels=3 */
} else if (strncmp(tok, "total_channels", 14) == 0) {
channels = atoi(tok +15);
}
resp = NULL;
}
char filename[32];
len = snprintf(filename, sizeof(filename), "ts2-%s.rrd", entry->name);
if (len < 0 || len >= sizeof(filename))
continue;
probe_submit(&plugin, filename, 0, "%d:%d", users, channels);
if (entry->errors > 0) {
log_print(LOG_ERROR, "plugin ts2: success (%s) after %d errors",
entry->name, entry->errors);
entry->errors = 0;
}
}
return 0;
}
static int init_cb(struct strtoken *tokens, void *privdata)
{
if (tokens->count != 2) {
log_print(LOG_ERROR, "p_ts2: parse error");
return -1;
}
struct server_entry *entry = malloc(sizeof(struct server_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "p_ts2: out of memory");
return -1;
}
entry->name = strdup(tokens->field[0]);
entry->errors = 0;
if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) {
log_print(LOG_ERROR, "p_ts2: invalid address: <%s>", tokens->field[1]);
free(entry->name);
free(entry);
return -1;
}
log_print(LOG_INFO, "p_ts2: added server '%s'", entry->name);
list_add_tail(&entry->list, &server_list);
return 0;
}
static int init(void)
{
ts2_resp_buf = malloc(TS2_RESP_SIZE);
if (ts2_resp_buf == NULL) {
log_print(LOG_ERROR, "p_ts2: out of memory");
return -1;
}
config_get_strtokens("p_ts2", "server", ",", 2, init_cb, NULL);
return 0;
}
static int fini(void)
{
struct server_entry *entry, *tmp;
list_for_each_entry_safe(entry, tmp, &server_list, list) {
free(entry->name);
free(entry);
}
free(ts2_resp_buf);
return 0;
}
struct sammler_plugin plugin = {
.name = "ts2",
.interval = 60,
.init = &init,
.fini = &fini,
.probe = &probe,
.get_ds = &get_ds,
};

61
probe.c
View File

@ -1,61 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "configfile.h"
#include "logging.h"
#include "network.h"
#include "rrdtool.h"
#define BUFSIZE 512
#define SUBMIT_NET_ONLY 0x01
static int submit_flags;
static const char *hostname;
int probe_init(void)
{
const char *fwd_only = config_get_string("global", "forward_only", "false");
submit_flags = 0;
if (!strncmp(fwd_only, "true", 4))
submit_flags |= SUBMIT_NET_ONLY;
static char hostname_buf[32];
if (gethostname(hostname_buf, sizeof(hostname_buf)) != 0)
strcpy(hostname_buf, "localhost");
hostname = config_get_string("global", "hostname", hostname_buf);
return 0;
}
int probe_submit(struct sammler_plugin *plugin, const char *filename, int ds_id, const char *fmt, ... )
{
char *buffer = malloc(BUFSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "probe_submit: out of memory");
return -1;
}
va_list az;
va_start(az, fmt);
int len = vsnprintf(buffer, BUFSIZE, fmt, az);
va_end(az);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "probe_submit: %s arguments too long", plugin->name);
free(buffer);
return -1;
}
net_submit(hostname, plugin->name, filename, ds_id, buffer);
if (!(submit_flags & SUBMIT_NET_ONLY))
rrd_submit(hostname, plugin->name, filename, ds_id, buffer);
free(buffer);
return 0;
}

View File

@ -1,9 +0,0 @@
#ifndef _PROBE_H_
#define _PROBE_H_
#include "plugins.h"
int probe_init(void);
int probe_submit(struct sammler_plugin *plugin, const char *filename, int ds_id, const char *fmt, ... );
#endif /* _PROBE_H_ */

260
rrdtool.c
View File

@ -17,7 +17,6 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#if (WITH_RRD)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -27,117 +26,178 @@
#include <rrd.h>
#include "configfile.h"
#include "helper.h"
#include "linebuffer.h"
#include "list.h"
#include "logging.h"
#include "config.h"
#include "plugins.h"
#define DEFAULT_STEP 10
#define ARGCMAX 64
#define ARGVSIZE 1024
#define RRDTOOL_CREATE 1
#define RRDTOOL_UPDATE 2
#define BUFSIZE 1024
static const char *rrd_dir;
int sammler_rrd_init(void)
static int append_rra_config(char *buffer, int size, int *pos)
{
rrd_dir = config_get_string("global", "rrd_dir", ".");
return 0;
struct conf_section *section;
struct conf_tupel *tupel;
int len, rra_cnt = 0;
section = config_get_section("global");
if (section == NULL) {
log_print(LOG_ERROR, "append_ds_config: conf-section 'global' not found");
return -1;
}
list_for_each_entry(tupel, &section->tupel, list) {
if (strcmp(tupel->option, "rra"))
continue;
len = snprintf(buffer + *pos, size - *pos, "%s ", tupel->parameter);
if (len < 0 || len >= size - *pos) {
log_print(LOG_ERROR, "append_ds_config: arguments too long");
return -1;
}
*pos += len;
rra_cnt++;
}
return rra_cnt;
}
static int append_rra_config(const char *parameter, void *privdata)
static int append_ds_config(char *buffer, int size, int *pos, int heartbeat, char **ds_def)
{
struct lbuf *buffer = (struct lbuf *)privdata;
int len, ds_cnt = 0;
char *dsbuild;
lbuf_printf(buffer, "%s ", parameter);
return 0;
dsbuild = malloc(BUFSIZE);
if (dsbuild == NULL) {
log_print(LOG_ERROR, "append_ds_config: out of memory");
return -1;
}
while (*ds_def != NULL) {
len = snprintf(dsbuild, BUFSIZE, *ds_def, heartbeat);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "append_ds_config: arguments too long");
free(dsbuild);
return -1;
}
len = snprintf(buffer + *pos, size - *pos, "%s ", dsbuild);
if (len < 0 || len >= size - *pos) {
log_print(LOG_ERROR, "append_ds_config: arguments too long");
free(dsbuild);
return -1;
}
*pos += len;
*ds_def++;
ds_cnt++;
}
free(dsbuild);
return ds_cnt;
}
static int do_rrd(int (*rrd_func)(int, char **), struct lbuf *buffer)
static int do_rrd(int mode, char *cmd)
{
size_t len;
char *cmd = lbuf_getdata(buffer, &len);
if (len < ARGVSIZE -1)
cmd[len] = '\0';
int argc;
char *argv[ARGCMAX];
int argc = strsplit(cmd, " \t\n", argv, ARGCMAX -1);
argc = strsplit(cmd, argv, ARGCMAX -1);
argv[argc] = NULL;
optind = 0;
rrd_clear_error();
int retval = rrd_func(argc, argv);
if (retval == -1) {
errno = 0;
log_print(LOG_ERROR, "rrd_func failed: %s: %s", argv[1], rrd_get_error());
}
if (mode == RRDTOOL_CREATE) {
if (rrd_create(argc, argv) == -1) {
errno = 0;
log_print(LOG_ERROR, "rrd_create failed: %s: %s",
argv[2], rrd_get_error());
return -1;
}
return retval;
} else if (mode == RRDTOOL_UPDATE) {
if (rrd_update(argc, argv) == -1) {
errno = 0;
log_print(LOG_ERROR, "rrd_update failed: %s: %s",
argv[2], rrd_get_error());
return -1;
}
}
return 0;
}
static int rrd_create_file(const char *filename, const char *pluginname, int ds_id)
static int rrd_create_file(char *filename, char **ds_def)
{
struct sammler_plugin *plugin = plugin_lookup(pluginname);
if (plugin == NULL) {
log_print(LOG_ERROR, "rrd_create_file: plugin not found (%s)", pluginname);
return -1;
}
int pos, step, heartbeat, retval;
char *buffer;
const char *ds_def = plugin->get_ds(ds_id);
if (ds_def == NULL) {
log_print(LOG_ERROR, "No vaild DS found (%s:%d)", plugin->name, ds_id);
return -1;
}
struct lbuf *buffer = lbuf_create(ARGVSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "rrd_create_file: out of memory");
return -1;
}
int ret = lbuf_printf(buffer, "create %s -s %d %s ", filename, plugin->interval, ds_def);
if (ret == -1) {
log_print(LOG_ERROR, "rrd_create_file: arguments too long");
lbuf_free(buffer);
return -1;
}
ret = config_get_strings("global", "rra", append_rra_config, buffer);
if (ret <= 0) {
lbuf_free(buffer);
return -1;
}
ret = do_rrd(&rrd_create, buffer);
lbuf_free(buffer);
return ret;
}
static int rrd_update_file(const char *filename, const char *values)
{
struct lbuf *buffer = lbuf_create(ARGVSIZE);
buffer = malloc(ARGVSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "append_ds_config: out of memory");
return -1;
}
int ret = lbuf_printf(buffer, "update %s N:%s", filename, values);
if (ret == -1) {
log_print(LOG_ERROR, "rrd_update_file: arguments too long");
lbuf_free(buffer);
step = config_get_int("global", "step", DEFAULT_STEP);
heartbeat = (step * 2) + (step / 2);
pos = snprintf(buffer, ARGVSIZE, "create %s -s %d ", filename, step);
if (pos < 0 || pos >= ARGVSIZE) {
log_print(LOG_ERROR, "rrd_create_file: arguments too long");
free(buffer);
return -1;
}
ret = do_rrd(&rrd_update, buffer);
lbuf_free(buffer);
return ret;
if (append_rra_config(buffer, ARGVSIZE, &pos) <= 0) {
free(buffer);
return -1;
}
if (append_ds_config(buffer, ARGVSIZE, &pos, heartbeat, ds_def) <= 0) {
free(buffer);
return -1;
}
retval = do_rrd(RRDTOOL_CREATE, buffer);
free(buffer);
return retval;
}
static int check_create_dir(const char *dir)
static int rrd_update_file(char *filename, char *values)
{
int pos, retval;
char *buffer;
buffer = malloc(ARGVSIZE);
if (buffer == NULL) {
log_print(LOG_ERROR, "append_ds_config: out of memory");
return -1;
}
pos = snprintf(buffer, ARGVSIZE, "update %s %lu:%s", filename, time(NULL), values);
if (pos < 0 || pos >= ARGVSIZE) {
log_print(LOG_ERROR, "rrd_update_file: arguments too long");
free(buffer);
return -1;
}
retval = do_rrd(RRDTOOL_UPDATE, buffer);
free(buffer);
return retval;
}
static int check_create_dir(char *dir)
{
struct stat statbuf;
if (stat(dir, &statbuf) == -1) {
@ -162,9 +222,9 @@ static int check_create_dir(const char *dir)
static int create_parent_dirs(char *filename)
{
char *nextslash = filename;
char *lastslash, *nextslash = filename;
char *lastslash = strrchr(filename, '/');
lastslash = strrchr(filename, '/');
if (lastslash == NULL) {
log_print(LOG_ERROR, "create_parent_dirs: invalid file name");
return -1;
@ -194,61 +254,63 @@ static int create_parent_dirs(char *filename)
return 0;
}
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data)
{
char *fullfile = malloc(BUFSIZE);
struct stat statbuf;
static char *rrd_dir = NULL;
char *fullfile, **ds_def;
int len;
if (rrd_dir == NULL)
rrd_dir = config_get_string("global", "rrd_dir", ".");
fullfile = malloc(BUFSIZE);
if (fullfile == NULL) {
log_print(LOG_ERROR, "rrd_submit: out of memory");
return -1;
return;
}
int len = snprintf(fullfile, BUFSIZE, "%s/%s/%s", rrd_dir, hostname, filename);
len = snprintf(fullfile, BUFSIZE, "%s/%s", rrd_dir, filename);
if (len < 0 || len >= BUFSIZE) {
log_print(LOG_ERROR, "rrd_submit: arguments too long");
free(fullfile);
return -1;
return;
}
struct stat statbuf;
if (stat(fullfile, &statbuf) == -1) {
if (errno == ENOENT) {
errno = 0;
if (create_parent_dirs(fullfile) == -1) {
free(fullfile);
return -1;
return;
}
if (rrd_create_file(fullfile, pluginname, ds_id) == -1) {
ds_def = plugins_get_ds(plugin, version, ds_id);
if (ds_def == NULL) {
log_print(LOG_ERROR, "No vaild DS found (%s v%d %d)", plugin, version, ds_id);
free(fullfile);
return -1;
return;
}
if (rrd_create_file(fullfile, ds_def) == -1) {
free(fullfile);
return;
}
} else {
log_print(LOG_ERROR, "rrd_submit: stat(%s):", fullfile);
free(fullfile);
return -1;
return;
}
} else if (!S_ISREG (statbuf.st_mode)) {
log_print(LOG_ERROR, "rrd_submit: stat(%s): Not a regular file!", fullfile);
free(fullfile);
return -1;
return;
}
rrd_update_file(fullfile, data);
free(fullfile);
return 0;
}
#else /* (WITH_RRD) */
int sammler_rrd_init(void)
{
return 0;
}
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
{
return 0;
}
#endif /* (WITH_RRD) */

View File

@ -1,7 +1,6 @@
#ifndef _RRDTOOL_H_
#define _RRDTOOL_H_
int sammler_rrd_init(void);
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data);
void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data);
#endif /* _RRDTOOL_H_ */

102
sammler.c
View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 03/2010 by Olaf Rempel *
* Copyright (C) 06/2006 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
@ -23,23 +23,13 @@
#include <string.h>
#include <getopt.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include "configfile.h"
#include "event.h"
#include "config.h"
#include "logging.h"
#include "network.h"
#include "rrdtool.h"
#include "pidfile.h"
#include "plugins.h"
#include "probe.h"
#include "signals.h"
#define DEFAULT_CONFIG "sammler.conf"
#define DEFAULT_LOGFILE "sammler.log"
#define DEFAULT_PIDFILE "sammler.pid"
static struct option opts[] = {
{"config", 1, 0, 'c'},
@ -48,23 +38,6 @@ static struct option opts[] = {
{0, 0, 0, 0}
};
static int restart_var;
static void trigger_restart(void *privdata)
{
restart_var = 1;
}
static int check_restart(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata)
{
if (restart_var == 1) {
restart_var = 0;
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
char *config = DEFAULT_CONFIG;
@ -93,7 +66,7 @@ int main(int argc, char *argv[])
break;
case '?': /* error */
exit(1);
exit(-1);
break;
default: /* unknown / all options parsed */
@ -102,72 +75,27 @@ int main(int argc, char *argv[])
} while (code != -1);
/* parse config file */
if (config_parse(config) < 0)
exit(1);
if (!debug) {
/* check pidfile */
const char *pidfile = config_get_string("global", "pidfile", DEFAULT_PIDFILE);
if (pidfile_check(pidfile, 1) != 0) {
log_print(LOG_ERROR, "sammler already running");
exit(1);
}
if (!config_parse(config))
exit(-1);
/* check logfile */
char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
if (logfile != NULL && debug == 0) {
/* start logging */
const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
if (log_init(logfile) < 0)
exit(1);
if (!log_init(logfile))
exit(-1);
/* zum daemon mutieren */
if (daemon(-1, 0) < 0) {
log_print(LOG_ERROR, "failed to daemonize");
exit(1);
}
/* create pidfile */
if (pidfile_create(pidfile) < 0) {
log_print(LOG_ERROR, "failed to create pidfile %s", pidfile);
exit(1);
}
daemon(-1, 0);
}
signal_init();
signal_add_callback(SIGHUP, trigger_restart, NULL);
log_print(LOG_EVERYTIME, "sammler started");
log_print(LOG_EVERYTIME, "sammler started (pid:%d)", getpid());
plugin_load_all();
while (1) {
if (probe_init())
break;
if (net_init())
break;
if (sammler_rrd_init())
break;
if (plugin_init())
break;
/* exited on restart / SIGUSR1 */
event_loop(check_restart, NULL, NULL);
plugin_close();
net_close();
log_close();
config_free();
if (config_parse(config) < 0)
break;
const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
if (!debug && log_init(logfile) < 0)
break;
log_print(LOG_EVERYTIME, "sammler restarted (pid:%d) ", getpid());
plugins_probe();
sleep (10);
}
return 0;

View File

@ -1,62 +1,35 @@
[global]
#hostname localhost
#listen 127.0.0.1:5000
#forward 127.0.0.1:5000
forward_only false
logfile sammler.log
pidfile sammler.pid
plugin_dir .
plugin p_stat.so
plugin p_load.so
plugin p_memory.so
plugin p_vmstat.so
plugin p_uptime.so
plugin p_netdev.so
plugin p_mount.so
#plugin p_ctstat.so
plugin p_rtstat.so
plugin p_random.so
rrd_dir rrd
plugin_dir plugins
plugin stat.so
plugin load.so
plugin memory.so
plugin vmstat.so
plugin uptime.so
plugin netdev.so
plugin mount.so
plugin diskstat.so
plugin ctstat.so
plugin rtstat.so
plugin random.so
#plugin mysql.so
#plugin apache.so
#plugin conntrack.so
#plugin hwmon.so
#plugin alixusv.so
#plugin ts2.so
#plugin diskstandby.so
#plugin hddtemp.so
step 10
# 1h(10s), 12h(1min), 48h(2min), 14d(15min), 4w(60min), 2y(12h)
rra RRA:MIN:0.5:1:360 RRA:AVERAGE:0.5:1:360 RRA:MAX:0.5:1:360
rra RRA:MIN:0.5:6:720 RRA:AVERAGE:0.5:6:720 RRA:MAX:0.5:6:720
rra RRA:MIN:0.5:12:1440 RRA:AVERAGE:0.5:12:1440 RRA:MAX:0.5:12:1440
rra RRA:MIN:0.5:90:1344 RRA:AVERAGE:0.5:90:1344 RRA:MAX:0.5:90:1344
rra RRA:MIN:0.5:360:1440 RRA:AVERAGE:0.5:360:1440 RRA:MAX:0.5:360:1440
rra RRA:MIN:0.5:4320:1440 RRA:AVERAGE:0.5:4320:1440 RRA:MAX:0.5:4320:1440
# 1h(10s), 48h(1min), 7d(5min), 4w(30min)
rra RRA:MIN:0.1:1:360
rra RRA:MIN:0.1:6:2880
rra RRA:MIN:0.1:30:2016
rra RRA:MIN:0.1:180:1344
[p_mysql]
#server name,host,user,password
rra RRA:AVERAGE:0.1:1:360
rra RRA:AVERAGE:0.1:6:2880
rra RRA:AVERAGE:0.1:30:2016
rra RRA:AVERAGE:0.1:180:1344
[p_apache]
#server name,url,user,password
[p_hwmon]
#temp board,/sys/class/hwmon/hwmon0/device/temp1_input
#temp cpu,/sys/class/hwmon/hwmon0/device/temp2_input
[p_alixusv]
#socket /var/run/alix-usvd.sock
[p_ts2]
#server localhost,127.0.0.1:51234
[p_diskstandby]
#device /dev/sda
[p_hddtemp]
#server test,127.0.0.1:7634
rra RRA:MAX:0.1:1:360
rra RRA:MAX:0.1:6:2880
rra RRA:MAX:0.1:30:2016
rra RRA:MAX:0.1:180:13446

View File

@ -1,896 +0,0 @@
<?php
define('CONFIG', '%%WWW_CONFIG%%');
define('BASE_DIR', '%%DATA_DIR%%');
define('RRDTOOL', '/usr/bin/rrdtool');
function setup_html($conf) {
echo "<html><head><title>sammler graph setup</title>\n";
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\"/>\n";
echo "</head><body>\n";
echo "<form method=\"POST\" action=\"{$_SERVER['SCRIPT_NAME']}?action=setup\">\n";
echo "<table>\n";
echo "<tr><td><b>Graph Height:</b></td>\n";
echo "<td><input type=\"text\" name=\"height\" value=\"{$conf['height']}\"></td></tr>\n";
echo "<tr><td><b>Graph Width:</b></td>\n";
echo "<td><input type=\"text\" name=\"width\" value=\"{$conf['width']}\"></td></tr>\n";
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
echo "<tr><td><b>Available Views:</b></td><td colspan=\"2\"></td><td><b>default</b></td></tr>\n";
foreach ($conf['views'] as $name => $value) {
echo "<tr><td>({$value}s)</td>\n";
echo "<td><input type=\"text\" name=\"views[$value]\" value=\"{$name}\"></td><td></td>\n";
if ($conf['default_view'] == $value)
echo "<td><input type=\"radio\" name=\"default_view\" value=\"{$value}\" checked=\"checked\"></td>\n";
else
echo "<td><input type=\"radio\" name=\"default_view\" value=\"{$value}\"></td>\n";
echo "</tr>\n";
}
echo "<tr><td><b>add view:</b></td><td><input type=\"text\" name=\"views[new]\"></td></tr>\n";
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
foreach ($conf['hosts'] as $hostid => $host) {
echo "<tr><td><b>Hostname:</b></td>\n";
echo "<td><input type=\"text\" name=\"hosts[{$hostid}][hostname]\" value=\"{$host['hostname']}\"></td>\n";
echo "<td><a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_host_up&host={$hostid}\">up</a>&nbsp;\n";
echo "<a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_host_down&host={$hostid}\">down</a></td>\n";
if ($host['show'])
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][show]\" checked=\"checked\">show</td>";
else
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][show]\">show</td>";
echo "</tr>\n";
foreach ($host['rrds'] as $rrdid => $rrd) {
echo "<tr><td>&nbsp;&nbsp;{$rrd['rrd']}</td>\n";
echo "<td><input type=\"text\" name=\"hosts[{$hostid}][rrds][{$rrdid}][title]\" value=\"{$rrd['title']}\"></td>\n";
echo "<td><a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_rrd_up&host={$hostid}&rrd={$rrdid}\">up</a>&nbsp;\n";
echo "<a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_rrd_down&host={$hostid}&rrd={$rrdid}\">down</a></td>\n";
if ($rrd['show'])
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][rrds][{$rrdid}][show]\" checked=\"checked\">show</td>";
else
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][rrds][{$rrdid}][show]\">show</td>";
echo "</tr>\n";
}
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
}
echo "<tr><td colspan=\"4\" align=\"center\">\n";
echo "<input type=\"button\" value=\"Show\" onClick=\"javascript:window.location.href='{$_SERVER['SCRIPT_NAME']}?action=show'\">&nbsp\n";
echo "<input type=\"submit\" value=\"Save Config\">&nbsp\n";
echo "<input type=\"button\" value=\"Rebuild Config\" onClick=\"javascript:window.location.href='{$_SERVER['SCRIPT_NAME']}?action=init'\">\n";
echo "</td></tr>\n";
echo "</table></form>\n";
echo "</body></html>\n";
}
function show_html($conf) {
echo "<html><head><title>Stats</title>\n";
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\"/>\n";
echo "</head><body>\n";
$hostid = isset($_GET['host']) ? $_GET['host'] : 0;
$view = isset($_GET['view']) ? $_GET['view'] : $conf['default_view'];
echo "<b>Select Host:</b>\n";
echo "<select name=\"host\" OnChange=\"document.location.href='{$_SERVER['SCRIPT_NAME']}?action=show&host='+this.value+'&view={$view}'\">\n";
foreach ($conf['hosts'] as $id => $host) {
if (!$host['show'])
continue;
if ($hostid == $id)
echo "<option value=\"{$id}\" selected=\"selected\">{$host['hostname']}</option>\n";
else
echo "<option value=\"{$id}\">{$host['hostname']}</option>\n";
}
echo "</select>&nbsp;\n";
echo "<td><select name=\"view\" OnChange=\"document.location.href='{$_SERVER['SCRIPT_NAME']}?action=show&host={$hostid}&view='+this.value\">\n";
foreach ($conf['views'] as $name => $value) {
if ($view == $value)
echo "<option value=\"{$value}\" selected=\"selected\">{$name}</option>\n";
else
echo "<option value=\"{$value}\">{$name}</option>\n";
}
echo "</select><br><br>\n";
foreach ($conf['hosts'][$hostid]['rrds'] as $rrdid => $rrd) {
if (!$rrd['show'])
continue;
echo "<img src=\"{$_SERVER['SCRIPT_NAME']}?action=rrd&host={$hostid}&rrd={$rrdid}&view={$view}\" border=\"0\"><br><br>\n";
}
echo "</body></html>\n";
}
function read_config($filename) {
$handle = @fopen($filename, "r");
if ($handle !== false && filesize($filename) > 0) {
$contents = fread($handle, filesize($filename));
fclose($handle);
return unserialize($contents);
}
}
function write_config($filename, $config) {
$handle = fopen($filename, "w+");
if ($handle !== false) {
$contents = serialize($config);
fwrite($handle, $contents);
fclose($handle);
}
}
function get_hostdirs() {
$retval = array();
$dh = opendir(BASE_DIR);
while (($file = readdir($dh)) !== false)
if (is_dir(BASE_DIR.$file) && $file != "." && $file != "..")
$retval[] = $file;
closedir($dh);
natsort($retval);
return $retval;
}
function get_rrdfiles($directory) {
$retval = array();
$dh = opendir(BASE_DIR.$directory);
while (($file = readdir($dh)) !== false) {
if (is_dir(BASE_DIR.$file))
continue;
if (strstr($file, "rrd") !== false)
$retval[] = $file;
}
closedir($dh);
natsort($retval);
return $retval;
}
function get_rrd_type($filename) {
$types = array_flip(array(
"cpu",
"load",
"memory",
"swap",
"proc",
"vmstat",
"random",
"uptime",
"hwmon",
"alixusv",
"net",
"rtstat",
"rtcache",
"ctstat",
"conntrack",
"disk",
"mount",
"apache",
"mysql",
"ts2"
));
$tmp1 = explode('-', $filename);
$tmp2 = explode('_', $tmp1[0]);
$type = $tmp2[0];
if (isset($types[$type]))
return $types[$type];
return $filename;
}
function rrd_sort($a, $b) {
if (!is_numeric($a['type']) && !is_numeric($b['type']))
return strcmp($a['type'], $b['type']);
if (is_numeric($a['type']) && !is_numeric($b['type']))
return -1;
if (!is_numeric($a['type']) && is_numeric($b['type']))
return +1;
if ($a['type'] > $b['type'])
return +1;
if ($a['type'] < $b['type'])
return -1;
return strcmp($a['title'], $b['title']);
}
function create_config() {
$conf = array();
$conf['default_view'] = 86400;
$conf['views'] = array("1 hour" => 3600,
"6 hours" => 21600,
"1 day" => 86400,
"1 week" => 604800,
"1 month" => 2678400);
$conf['height'] = 120;
$conf['width'] = 800;
$conf['hosts'] = array();
$hosts = get_hostdirs();
foreach ($hosts as $host) {
$rrds = array();
$tmp = get_rrdfiles($host);
foreach ($tmp as $file) {
$basename = str_replace(".rrd", "", basename($file));
$rrds[] = array(
'show' => true,
'title' => $basename,
'rrd' => "$host/$file",
'type' => get_rrd_type($basename),
);
}
uasort($rrds, rrd_sort);
$conf['hosts'][] = array(
'hostname' => $host,
'show' => true,
'rrds' => $rrds,
);
}
return $conf;
}
function setup($conf) {
if (isset($_GET['sub']) && $_GET['sub'] == "move_host_up") {
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
if (isset($conf['hosts'][$hostid]) && isset($conf['hosts'][$hostid -1])) {
$a = $conf['hosts'][$hostid];
$b = $conf['hosts'][$hostid -1];
$conf['hosts'][$hostid] = $b;
$conf['hosts'][$hostid -1] = $a;
}
return $conf;
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_host_down") {
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
if (isset($conf['hosts'][$hostid]) && isset($conf['hosts'][$hostid +1])) {
$a = $conf['hosts'][$hostid];
$b = $conf['hosts'][$hostid +1];
$conf['hosts'][$hostid] = $b;
$conf['hosts'][$hostid +1] = $a;
}
return $conf;
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_rrd_up") {
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
if (isset($conf['hosts'][$hostid]['rrds'][$rrdid]) && isset($conf['hosts'][$hostid]['rrds'][$rrdid -1])) {
$a = $conf['hosts'][$hostid]['rrds'][$rrdid];
$b = $conf['hosts'][$hostid]['rrds'][$rrdid -1];
$conf['hosts'][$hostid]['rrds'][$rrdid] = $b;
$conf['hosts'][$hostid]['rrds'][$rrdid -1] = $a;
}
return $conf;
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_rrd_down") {
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
if (isset($conf['hosts'][$hostid]['rrds'][$rrdid]) && isset($conf['hosts'][$hostid]['rrds'][$rrdid +1])) {
$a = $conf['hosts'][$hostid]['rrds'][$rrdid];
$b = $conf['hosts'][$hostid]['rrds'][$rrdid +1];
$conf['hosts'][$hostid]['rrds'][$rrdid] = $b;
$conf['hosts'][$hostid]['rrds'][$rrdid +1] = $a;
}
return $conf;
} else if (!empty($_POST)) {
$conf['default_view'] = $_POST['default_view'];
$conf['height'] = $_POST['height'];
$conf['width'] = $_POST['width'];
$conf['views'] = array();
foreach ($_POST['views'] as $name) {
if (empty($name))
continue;
$tmp = strtotime($name);
if ($tmp != -1)
$conf['views'][$name] = $tmp - time();
}
natsort($conf['views']);
foreach ($_POST['hosts'] as $hostid => $host) {
$conf['hosts'][$hostid]['hostname'] = $host['hostname'];
$conf['hosts'][$hostid]['show'] = ($host['show'] == "on");
foreach ($host['rrds'] as $rrdid => $rrd) {
$conf['hosts'][$hostid]['rrds'][$rrdid]['title'] = $_POST['hosts'][$hostid]['rrds'][$rrdid]['title'];
$conf['hosts'][$hostid]['rrds'][$rrdid]['show'] = ($_POST['hosts'][$hostid]['rrds'][$rrdid]['show'] == "on");
}
}
return $conf;
} else {
setup_html($conf);
}
}
function show_rrd($conf) {
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
if (!isset($conf['hosts'][$hostid]['rrds'][$rrdid]['rrd']))
return;
$view = isset($_GET['view']) ? -$_GET['view'] : -$conf['default_view'];
$rrdfile = BASE_DIR.$conf['hosts'][$hostid]['rrds'][$rrdid]['rrd'];
$title = $conf['hosts'][$hostid]['rrds'][$rrdid]['title'];
$height = $conf['height'];
$width = $conf['width'];
$cmd = RRDTOOL." graph - --imgformat PNG --start {$view} --end -10 --title \"{$title}\" --rigid ";
$tmp1 = explode('-', basename($rrdfile));
$tmp2 = explode('_', $tmp1[0]);
$tmp3 = explode('.', $tmp2[0]);
switch ($tmp3[0]) {
case 'alixusv':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale --vertical-label=\"Voltage\" ".
"DEF:a={$rrdfile}:ibat:AVERAGE ".
"DEF:b={$rrdfile}:ubat:AVERAGE ".
"DEF:c={$rrdfile}:uin:AVERAGE ".
'CDEF:aa=a,50,/ '.
'CDEF:bb=b,1000,/ '.
'CDEF:cc=c,1000,/ '.
'CDEF:perr=aa,UN,INF,UNKN,IF CDEF:nerr=aa,UN,-INF,UNKN,IF '.
'HRULE:0#808080 AREA:perr#FFD0D0 AREA:nerr#FFD0D0 '.
'LINE2:aa#FF0000:"Ibat " GPRINT:a:LAST:"Current\:%7.0lf%smA" GPRINT:a:MIN:"Minimum\:%7.0lf%smA" GPRINT:a:MAX:"Maximum\:%7.0lf%smA\n" '.
'LINE2:bb#00CF00:"Ubat " GPRINT:bb:LAST:"Current\:%7.3lf%s V" GPRINT:bb:MIN:"Minimum\:%7.3lf%s V" GPRINT:bb:MAX:"Maximum\:%7.3lf%s V\n" '.
'LINE2:cc#0000FF:"Uin " GPRINT:cc:LAST:"Current\:%7.3lf%s V" GPRINT:cc:MIN:"Minimum\:%7.3lf%s V" GPRINT:cc:MAX:"Maximum\:%7.3lf%s V\n" '.
'';
break;
case 'apache':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Workers\" ".
"DEF:aa={$rrdfile}:total_accesses:AVERAGE ".
"DEF:b={$rrdfile}:total_kbytes:AVERAGE ".
"DEF:c={$rrdfile}:busy_workers:AVERAGE ".
"DEF:d={$rrdfile}:idle_workers:AVERAGE ".
'CDEF:a=aa,60,* '.
'CDEF:err=aa,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:c#FF0000:"Busy Workers" GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:d#00CF00:"Idle Workers" GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE2:a#0000FF:"Accesses " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'';
break;
case 'cpu':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"percent\" ".
"DEF:a={$rrdfile}:user:AVERAGE ".
"DEF:b={$rrdfile}:nice:AVERAGE ".
"DEF:c={$rrdfile}:system:AVERAGE ".
"DEF:e={$rrdfile}:iowait:AVERAGE ".
"DEF:f={$rrdfile}:irq:AVERAGE ".
"DEF:g={$rrdfile}:softirq:AVERAGE ".
"DEF:h={$rrdfile}:steal:AVERAGE ".
"DEF:amax={$rrdfile}:user:MAX ".
"DEF:bmax={$rrdfile}:nice:MAX ".
"DEF:cmax={$rrdfile}:system:MAX ".
"DEF:emax={$rrdfile}:iowait:MAX ".
"DEF:fmax={$rrdfile}:irq:MAX ".
"DEF:gmax={$rrdfile}:softirq:MAX ".
"DEF:hmax={$rrdfile}:steal:MAX ".
"CDEF:allmax=amax,bmax,cmax,emax,fmax,gmax,hmax,+,+,+,+,+,+ ".
'CDEF:err=allmax,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:allmax#C0C0C0 LINE1:allmax#808080 '.
'AREA:c#FF0000:"System " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:f#EA8F00:"IRQ " GPRINT:f:LAST:"Current\:%8.2lf %s" GPRINT:f:AVERAGE:"Average\:%8.2lf %s" GPRINT:f:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:g#FFFF00:"Soft-IRQ" GPRINT:g:LAST:"Current\:%8.2lf %s" GPRINT:g:AVERAGE:"Average\:%8.2lf %s" GPRINT:g:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:h#0040FF:"IO-Wait " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:a#00CFCF:"User " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#00CF00:"Nice " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:h#FF00FF:"Stolen " GPRINT:h:LAST:"Current\:%8.2lf %s" GPRINT:h:AVERAGE:"Average\:%8.2lf %s" GPRINT:h:MAX:"Maximum\:%8.2lf %s\n" ';
break;
case 'conntrack':
$tmp3 = explode('.', $tmp1[1]);
switch ($tmp3[0]) {
case 'proto':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"Connections\" ".
"DEF:a={$rrdfile}:tcp:AVERAGE ".
"DEF:b={$rrdfile}:udp:AVERAGE ".
"DEF:c={$rrdfile}:unknown:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:a#00CF00:"tcp " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#0000FF:"udp " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:c#FF0000:"unknown" GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" ';
break;
case 'tcp':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"TCP Connections\" ".
"DEF:a={$rrdfile}:none:AVERAGE ".
"DEF:b={$rrdfile}:syn_sent:AVERAGE ".
"DEF:c={$rrdfile}:syn_recv:AVERAGE ".
"DEF:d={$rrdfile}:established:AVERAGE ".
"DEF:e={$rrdfile}:fin_wait:AVERAGE ".
"DEF:f={$rrdfile}:close_wait:AVERAGE ".
"DEF:g={$rrdfile}:last_ack:AVERAGE ".
"DEF:h={$rrdfile}:time_wait:AVERAGE ".
"DEF:i={$rrdfile}:close:AVERAGE ".
"DEF:j={$rrdfile}:listen:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:b#FF0000:"SYN_SEND " GPRINT:b:LAST:"Current\:%8.2lf" GPRINT:b:AVERAGE:"Average\:%8.2lf" GPRINT:b:MAX:"Maximum\:%8.2lf\n" '.
'STACK:f#FF00FF:"CLOSE_WAIT " GPRINT:f:LAST:"Current\:%8.2lf" GPRINT:f:AVERAGE:"Average\:%8.2lf" GPRINT:f:MAX:"Maximum\:%8.2lf\n" '.
'STACK:g#0000FF:"LAST_ACK " GPRINT:g:LAST:"Current\:%8.2lf" GPRINT:g:AVERAGE:"Average\:%8.2lf" GPRINT:g:MAX:"Maximum\:%8.2lf\n" '.
'STACK:h#007FFF:"TIME_WAIT " GPRINT:h:LAST:"Current\:%8.2lf" GPRINT:h:AVERAGE:"Average\:%8.2lf" GPRINT:h:MAX:"Maximum\:%8.2lf\n" '.
'STACK:c#00FFFF:"SYN_RECV " GPRINT:c:LAST:"Current\:%8.2lf" GPRINT:c:AVERAGE:"Average\:%8.2lf" GPRINT:c:MAX:"Maximum\:%8.2lf\n" '.
'STACK:d#00FF00:"ESTABLISHED" GPRINT:d:LAST:"Current\:%8.2lf" GPRINT:d:AVERAGE:"Average\:%8.2lf" GPRINT:d:MAX:"Maximum\:%8.2lf\n" '.
'STACK:e#FFFF00:"FIN_WAIT " GPRINT:e:LAST:"Current\:%8.2lf" GPRINT:e:AVERAGE:"Average\:%8.2lf" GPRINT:e:MAX:"Maximum\:%8.2lf\n" '.
'STACK:i#FF7F00:"CLOSE " GPRINT:i:LAST:"Current\:%8.2lf" GPRINT:i:AVERAGE:"Average\:%8.2lf" GPRINT:i:MAX:"Maximum\:%8.2lf\n" ';
break;
default:
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"Connections\" ".
"DEF:a={$rrdfile}:total:AVERAGE ".
"DEF:b={$rrdfile}:local:AVERAGE ".
"DEF:c={$rrdfile}:nated:AVERAGE ".
"DEF:d={$rrdfile}:unreplied:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#000000:"Total " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'AREA:b#00CF00:"Local " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:c#0000FF:"NATed " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:d#FF0000:"Unreplied" GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" ';
break;
}
break;
case 'ctstat':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
"DEF:a={$rrdfile}:searched:AVERAGE ".
"DEF:b={$rrdfile}:found:AVERAGE ".
"DEF:c={$rrdfile}:new:AVERAGE ".
"DEF:d={$rrdfile}:invalid:AVERAGE ".
"DEF:e={$rrdfile}:ignore:AVERAGE ".
"DEF:f={$rrdfile}:delete:AVERAGE ".
"DEF:g={$rrdfile}:delete_list:AVERAGE ".
"DEF:h={$rrdfile}:insert:AVERAGE ".
"DEF:i={$rrdfile}:insert_failed:AVERAGE ".
"DEF:j={$rrdfile}:drop:AVERAGE ".
"DEF:k={$rrdfile}:early_drop:AVERAGE ".
"DEF:l={$rrdfile}:icmp_error:AVERAGE ".
"DEF:m={$rrdfile}:expect_new:AVERAGE ".
"DEF:n={$rrdfile}:expect_create:AVERAGE ".
"DEF:o={$rrdfile}:expect_delete:AVERAGE ".
'CDEF:ii=i,-1,* '.
'CDEF:jj=j,-1,* '.
'CDEF:kk=k,-1,* '.
'CDEF:ll=l,-1,* '.
'CDEF:mm=m,-1,* '.
'CDEF:nn=n,-1,* '.
'CDEF:oo=o,-1,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#FF0000:"searched " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:b#FF00FF:"found " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:c#0000FF:"new " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:d#007FFF:"invalid " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:e#00FFFF:"ignore " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:f#00FF00:"delete " GPRINT:f:LAST:"Current\:%8.0lf" GPRINT:f:AVERAGE:"Average\:%8.0lf" GPRINT:f:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:g#FFFF00:"delete_list " GPRINT:g:LAST:"Current\:%8.0lf" GPRINT:g:AVERAGE:"Average\:%8.0lf" GPRINT:g:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:h#FF7F00:"insert " GPRINT:h:LAST:"Current\:%8.0lf" GPRINT:h:AVERAGE:"Average\:%8.0lf" GPRINT:h:MAX:"Maximum\:%8.0lf\n" '.
'HRULE:0#000000:"-\n" '.
'LINE1:ii#FF0000:"insert_failed " GPRINT:i:LAST:"Current\:%8.0lf" GPRINT:i:AVERAGE:"Average\:%8.0lf" GPRINT:i:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:jj#FF00FF:"drop " GPRINT:j:LAST:"Current\:%8.0lf" GPRINT:j:AVERAGE:"Average\:%8.0lf" GPRINT:j:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:kk#0000FF:"early_drop " GPRINT:k:LAST:"Current\:%8.0lf" GPRINT:k:AVERAGE:"Average\:%8.0lf" GPRINT:k:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:ll#007FFF:"icmp_errore " GPRINT:l:LAST:"Current\:%8.0lf" GPRINT:l:AVERAGE:"Average\:%8.0lf" GPRINT:l:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:mm#00FFFF:"expect_new " GPRINT:m:LAST:"Current\:%8.0lf" GPRINT:m:AVERAGE:"Average\:%8.0lf" GPRINT:m:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:nn#00FF00:"expect_create " GPRINT:n:LAST:"Current\:%8.0lf" GPRINT:n:AVERAGE:"Average\:%8.0lf" GPRINT:n:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:oo#FFFF00:"expect_delete " GPRINT:o:LAST:"Current\:%8.0lf" GPRINT:o:AVERAGE:"Average\:%8.0lf" GPRINT:o:MAX:"Maximum\:%8.0lf\n" ';
break;
case 'disk':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"sectors\" ".
"DEF:a={$rrdfile}:read_cnt:AVERAGE ".
"DEF:b={$rrdfile}:read_sec:AVERAGE ".
"DEF:c={$rrdfile}:read_ms:AVERAGE ".
"DEF:dd={$rrdfile}:write_cnt:AVERAGE ".
"DEF:ee={$rrdfile}:write_cnt:AVERAGE ".
"DEF:ff={$rrdfile}:write_ms:AVERAGE ".
'CDEF:d=dd,-1,* '.
'CDEF:e=ee,-1,* '.
'CDEF:f=ff,-1,* '.
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=dd,UN,-INF,UNKN,IF '.
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
'LINE1:a#FF0000:"read_count " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:b#FF00FF:"read_sectors " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:c#0000FF:"sectors / ms " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:d#FF0000:"write_count " GPRINT:dd:LAST:"Current\:%8.0lf" GPRINT:dd:AVERAGE:"Average\:%8.0lf" GPRINT:dd:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:e#FF00FF:"write_sectors " GPRINT:ee:LAST:"Current\:%8.0lf" GPRINT:ee:AVERAGE:"Average\:%8.0lf" GPRINT:ee:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:f#0000FF:"writes / ms " GPRINT:ff:LAST:"Current\:%8.0lf" GPRINT:ff:AVERAGE:"Average\:%8.0lf" GPRINT:ff:MAX:"Maximum\:%8.0lf\n" '.
'';
break;
case 'diskstandby':
$height /= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Active\" ".
"DEF:a={$rrdfile}:active:AVERAGE ".
"CDEF:b=1,a,- ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:a#FF0000:"Active\n" '.
'STACK:b#00CF00:"Standby" ';
break;
case 'hddtemp':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Temperature\" ".
"DEF:a={$rrdfile}:temperature:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:a#00CF00:"Temperature" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:a#404040 ';
break;
case 'hwmon':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Temperature\" ".
"DEF:a={$rrdfile}:temp:AVERAGE ".
"CDEF:aa=a,1000,/ ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:aa#00CF00:"Temperature" GPRINT:aa:LAST:"Current\:%8.2lf %s" GPRINT:aa:AVERAGE:"Average\:%8.2lf %s" GPRINT:aa:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:aa#404040 ';
break;
case 'load':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"load\" ".
"DEF:a={$rrdfile}:1min:MAX ".
"DEF:b={$rrdfile}:5min:MAX ".
"DEF:c={$rrdfile}:15min:MAX ".
'CDEF:x=a,b,c,MAX,MAX '.
'CDEF:err=x,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:a#EACC00:" 1 Minute Maximum " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
'AREA:b#EA8F00:" 5 Minute Maximum " GPRINT:b:LAST:"Current\:%8.2lf %s\n" '.
'AREA:c#FF0000:"15 Minute Maximum " GPRINT:c:LAST:"Current\:%8.2lf %s\n" '.
'LINE1:x#404040:"Total"';
break;
case 'memory':
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
"DEF:aa={$rrdfile}:total:AVERAGE ".
"DEF:bb={$rrdfile}:free:AVERAGE ".
"DEF:cc={$rrdfile}:buffers:AVERAGE ".
"DEF:dd={$rrdfile}:cached:AVERAGE ".
'CDEF:a=aa,1024,* '.
'CDEF:b=bb,1024,* '.
'CDEF:c=cc,1024,* '.
'CDEF:d=dd,1024,* '.
'CDEF:x=aa,bb,cc,dd,+,+,-,1024,* '.
'CDEF:xc=x,c,+ '.
'CDEF:xcd=x,c,d,+,+ '.
'CDEF:err=xcd,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#000000:"Total Memory " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
'AREA:x#FF0000:"Used Memory " GPRINT:x:LAST:"Current\:%8.2lf %s" GPRINT:x:AVERAGE:"Average\:%8.2lf %s" GPRINT:x:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:c#FF7D00:"Buffer Memory " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:d#FFC73B:"Cache Memory " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#00CF00:"Free Memory " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:x#404040 LINE1:xc#404040 LINE1:xcd#404040';
break;
case 'mount':
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
"DEF:aa={$rrdfile}:block_total:AVERAGE ".
"DEF:cc={$rrdfile}:block_free:AVERAGE ".
'CDEF:a=aa,1024,* '.
'CDEF:b=aa,cc,-,1024,* '.
'CDEF:c=cc,1024,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#000000:"Total " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
'AREA:b#FF0000:"Used " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:c#00CF00:"Free " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:b#404040 ';
break;
case 'mysql':
switch ($tmp1[1]) {
case 'commands':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"commands\" ".
"DEF:aa={$rrdfile}:com_delete:AVERAGE ".
"DEF:bb={$rrdfile}:com_insert:AVERAGE ".
"DEF:cc={$rrdfile}:com_select:AVERAGE ".
"DEF:dd={$rrdfile}:com_update:AVERAGE ".
"DEF:ee={$rrdfile}:questions:AVERAGE ".
'CDEF:a=aa,60,* '.
'CDEF:b=bb,60,* '.
'CDEF:c=cc,60,* '.
'CDEF:d=dd,60,* '.
'CDEF:e=ee,60,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:e#0000FF:"All Commands " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
'AREA:a#FF0000:"DELETE ... " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#FF7D00:"INSERT ... " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:d#FFC73B:"UPDATE ... " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:c#00CF00:"SELECT ... " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'';
break;
case 'qcache':
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"???\" ".
"DEF:a={$rrdfile}:qc_free_blocks:AVERAGE ".
"DEF:b={$rrdfile}:qc_free_memory:AVERAGE ".
"DEF:cc={$rrdfile}:qc_hits:AVERAGE ".
"DEF:dd={$rrdfile}:qc_inserts:AVERAGE ".
"DEF:ee={$rrdfile}:qc_lowmem_prunes:AVERAGE ".
"DEF:ff={$rrdfile}:qc_not_cached:AVERAGE ".
"DEF:g={$rrdfile}:qc_queries_in_cache:AVERAGE ".
"DEF:h={$rrdfile}:qc_total_blocks:AVERAGE ".
'CDEF:c=cc,60,* '.
'CDEF:d=dd,60,* '.
'CDEF:e=ee,60,* '.
'CDEF:f=ff,60,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#FF0000:"qc_free_blocks " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:b#FFFF00:"qc_free_memory " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:c#00FF00:"qc_hits " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:d#00FFFF:"qc_inserts " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:e#0000FF:"qc_lowmemprunes " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:f#FF00FF:"qc_not_cached " GPRINT:f:LAST:"Current\:%8.2lf %s" GPRINT:f:AVERAGE:"Average\:%8.2lf %s" GPRINT:f:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:g#FF00FF:"qc_queries_in_cache" GPRINT:g:LAST:"Current\:%8.2lf %s" GPRINT:g:AVERAGE:"Average\:%8.2lf %s" GPRINT:g:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:h#000000:"qc_total_blocks " GPRINT:h:LAST:"Current\:%8.2lf %s" GPRINT:h:AVERAGE:"Average\:%8.2lf %s" GPRINT:h:MAX:"Maximum\:%8.2lf %s\n" '.
'';
break;
case 'threads':
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"threads\" ".
"DEF:a={$rrdfile}:threads_cached:AVERAGE ".
"DEF:b={$rrdfile}:threads_connected:AVERAGE ".
"DEF:cc={$rrdfile}:threads_created:AVERAGE ".
"DEF:d={$rrdfile}:threads_running:AVERAGE ".
'CDEF:c=cc,60,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:c#00CF00:"threads created " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:d#FF0000:"threads running " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:b#00FFFF:"threads connected" GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:a#0000FF:"threads cached " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'';
break;
case 'traffic':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"bytes per second\" ".
"DEF:imax={$rrdfile}:bytes_received:MAX ".
"DEF:iavg={$rrdfile}:bytes_received:AVERAGE ".
"DEF:imin={$rrdfile}:bytes_received:MIN ".
"DEF:omax={$rrdfile}:bytes_sent:MAX ".
"DEF:oavg={$rrdfile}:bytes_sent:AVERAGE ".
"DEF:omin={$rrdfile}:bytes_sent:MIN ".
'CDEF:omaxn=omax,-1,* CDEF:oavgn=oavg,-1,* CDEF:ominn=omin,-1,* '.
'CDEF:imid=imax,imin,- CDEF:omid=omaxn,ominn,- '.
'CDEF:oerr=oavg,UN,INF,UNKN,IF CDEF:ierr=iavg,UN,-INF,UNKN,IF '.
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
'AREA:imin STACK:imid#A0FFA0:"min/max Inbound " GPRINT:imin:MIN:"%6.2lf%s" GPRINT:imax:MAX:"%6.2lf%s" '.
'LINE1:imin#a0a0a0 LINE1:imax#a0a0a0 LINE1:iavg#008000:"avg Inbound " '.
'GPRINT:iavg:MIN:"min\: %6.2lf%s" GPRINT:iavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:iavg:MAX:"max\: %6.2lf%s\n" '.
'AREA:ominn STACK:omid#C0C0FF:"min/max Outbound" GPRINT:omin:MIN:"%6.2lf%s" GPRINT:omax:MAX:"%6.2lf%s" '.
'LINE1:ominn#a0a0a0 LINE1:omaxn#a0a0a0 LINE1:oavgn#000080:"avg Outbound" '.
'GPRINT:oavg:MIN:"min\: %6.2lf%s" GPRINT:oavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:oavg:MAX:"max\: %6.2lf%s\n" ';
break;
}
break;
case 'net':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"bytes per second\" ".
"DEF:imax={$rrdfile}:byte_in:MAX ".
"DEF:iavg={$rrdfile}:byte_in:AVERAGE ".
"DEF:imin={$rrdfile}:byte_in:MIN ".
"DEF:omax={$rrdfile}:byte_out:MAX ".
"DEF:oavg={$rrdfile}:byte_out:AVERAGE ".
"DEF:omin={$rrdfile}:byte_out:MIN ".
'CDEF:omaxn=omax,-1,* CDEF:oavgn=oavg,-1,* CDEF:ominn=omin,-1,* '.
'CDEF:imid=imax,imin,- CDEF:omid=omaxn,ominn,- '.
'CDEF:oerr=oavg,UN,INF,UNKN,IF CDEF:ierr=iavg,UN,-INF,UNKN,IF '.
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
'AREA:imin#E0FFE0 STACK:imid#A0FFA0:"min/max Inbound " GPRINT:imin:MIN:"%6.2lf%s" GPRINT:imax:MAX:"%6.2lf%s" '.
'LINE1:imin#a0a0a0 LINE1:imax#a0a0a0 LINE1:iavg#008000:"avg Inbound " '.
'GPRINT:iavg:MIN:"min\: %6.2lf%s" GPRINT:iavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:iavg:MAX:"max\: %6.2lf%s\n" '.
'AREA:ominn#E0E0FF STACK:omid#C0C0FF:"min/max Outbound" GPRINT:omin:MIN:"%6.2lf%s" GPRINT:omax:MAX:"%6.2lf%s" '.
'LINE1:ominn#a0a0a0 LINE1:omaxn#a0a0a0 LINE1:oavgn#000080:"avg Outbound" '.
'GPRINT:oavg:MIN:"min\: %6.2lf%s" GPRINT:oavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:oavg:MAX:"max\: %6.2lf%s\n" ';
break;
case 'proc':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"per second\" ".
"DEF:a={$rrdfile}:intr:AVERAGE ".
"DEF:b={$rrdfile}:ctxt:AVERAGE ".
"DEF:c={$rrdfile}:fork:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:b#00AF00:"Context " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:a#FF0000:"Interrupts" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:c#0000FF:"Forks " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" ';
break;
case 'random':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"bytes\" ".
"DEF:a={$rrdfile}:entropy:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:a#00CF00:"Available Entropy" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:a#404040 ';
break;
case 'rtcache':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
"DEF:a={$rrdfile}:entries:AVERAGE ".
"DEF:b={$rrdfile}:gc_total:AVERAGE ".
"DEF:c={$rrdfile}:gc_ignored:AVERAGE ".
"DEF:d={$rrdfile}:gc_goal_miss:AVERAGE ".
"DEF:e={$rrdfile}:gc_dst_overflow:AVERAGE ".
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#FF0000:"entries " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:b#FF00FF:"gc_total " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:c#0000FF:"gc_ignored " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:d#007FFF:"gc_goal_miss " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:e#00FFFF:"gc_dst_overflow " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" ';
break;
case 'rtstat':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
"DEF:a={$rrdfile}:in_hit:AVERAGE ".
"DEF:b={$rrdfile}:in_slow_tot:AVERAGE ".
"DEF:c={$rrdfile}:in_slow_mc:AVERAGE ".
"DEF:d={$rrdfile}:in_no_route:AVERAGE ".
"DEF:e={$rrdfile}:in_brd:AVERAGE ".
"DEF:f={$rrdfile}:in_martian_dst:AVERAGE ".
"DEF:g={$rrdfile}:in_martian_src:AVERAGE ".
"DEF:h={$rrdfile}:in_hlist_search:AVERAGE ".
"DEF:i={$rrdfile}:out_hit:AVERAGE ".
"DEF:j={$rrdfile}:out_slow_tot:AVERAGE ".
"DEF:k={$rrdfile}:out_slow_mc:AVERAGE ".
"DEF:l={$rrdfile}:out_hlist_search:AVERAGE ".
'CDEF:ii=i,-1,* '.
'CDEF:jj=j,-1,* '.
'CDEF:kk=k,-1,* '.
'CDEF:ll=l,-1,* '.
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=i,UN,-INF,UNKN,IF '.
'AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
'LINE1:a#FF0000:"in_hit " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:b#FF00FF:"in_slow_tot " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:c#0000FF:"in_slow_mc " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:d#007FFF:"in_no_route " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:e#00FFFF:"in_brd " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:f#00FF00:"in_martian_dst " GPRINT:f:LAST:"Current\:%8.0lf" GPRINT:f:AVERAGE:"Average\:%8.0lf" GPRINT:f:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:g#FFFF00:"in_martian_src " GPRINT:g:LAST:"Current\:%8.0lf" GPRINT:g:AVERAGE:"Average\:%8.0lf" GPRINT:g:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:h#FF7F00:"in_hlist_search " GPRINT:h:LAST:"Current\:%8.0lf" GPRINT:h:AVERAGE:"Average\:%8.0lf" GPRINT:h:MAX:"Maximum\:%8.0lf\n" '.
'HRULE:0#FF0000:"-\n" '.
'LINE1:ii#FF0000:"out_hit " GPRINT:i:LAST:"Current\:%8.0lf" GPRINT:i:AVERAGE:"Average\:%8.0lf" GPRINT:i:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:jj#FF00FF:"out_slow_tot " GPRINT:j:LAST:"Current\:%8.0lf" GPRINT:j:AVERAGE:"Average\:%8.0lf" GPRINT:j:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:kk#0000FF:"out_slow_mc " GPRINT:k:LAST:"Current\:%8.0lf" GPRINT:k:AVERAGE:"Average\:%8.0lf" GPRINT:k:MAX:"Maximum\:%8.0lf\n" '.
'LINE1:ll#FF7F00:"out_hlist_search " GPRINT:l:LAST:"Current\:%8.0lf" GPRINT:l:AVERAGE:"Average\:%8.0lf" GPRINT:l:MAX:"Maximum\:%8.0lf\n" ';
break;
case 'swap':
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
"DEF:aa={$rrdfile}:total:AVERAGE ".
"DEF:bb={$rrdfile}:free:AVERAGE ".
'CDEF:a=aa,1024,* '.
'CDEF:b=bb,1024,* '.
'CDEF:x=aa,bb,-,1024,* '.
'CDEF:err=a,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'LINE1:a#000000:"Total Swap " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
'AREA:x#FF0000:"Used Swap " GPRINT:x:LAST:"Current\:%8.2lf %s" GPRINT:x:AVERAGE:"Average\:%8.2lf %s" GPRINT:x:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#00CF00:"Free Swap " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" ';
break;
case 'ts2':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"users/chans\" ".
"DEF:users={$rrdfile}:users:AVERAGE ".
"DEF:chans={$rrdfile}:channels:AVERAGE ".
'CDEF:err=users,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:chans#00CF00:"Channels \n" '.
'LINE1:users#002A97:"Users "';
break;
case 'uptime':
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"days\" ".
"DEF:ups={$rrdfile}:uptime:AVERAGE ".
"DEF:idles={$rrdfile}:idletime:AVERAGE ".
'CDEF:up=ups,86400,/ '.
'CDEF:idle=idles,86400,/ '.
'CDEF:err=ups,UN,INF,UNKN,IF '.
'AREA:err#FFD0D0 '.
'AREA:up#00CF00:"Uptime \n" '.
'LINE1:idle#002A97:"Idletime "';
break;
case 'vmstat':
$height *= 2;
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"allocs\" ".
"DEF:a={$rrdfile}:pgalloc_high:AVERAGE ".
"DEF:b={$rrdfile}:pgalloc_normal:AVERAGE ".
"DEF:c={$rrdfile}:pgalloc_dma:AVERAGE ".
"DEF:d={$rrdfile}:pgfree:AVERAGE ".
"DEF:e={$rrdfile}:pgfault:AVERAGE ".
"CDEF:ee=e,-1,* ".
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=e,UN,-INF,UNKN,IF '.
'AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
'HRULE:0#FF0000: '.
'AREA:c#FF0000:"pgalloc_dma " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:b#00CF00:"pgalloc_normal " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
'STACK:a#00CFCF:"pgalloc_high " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:d#FF7D00:"pgfree " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
'AREA:ee#0040FF:"pgfault " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
'LINE1:ee#002A97 ';
break;
}
header('Content-type: image/x-png');
passthru($cmd);
die();
}
$action = $_GET['action'];
switch ($action) {
case 'init':
$conf = create_config();
write_config(CONFIG, $conf);
header("Location: {$_SERVER['SCRIPT_NAME']}?action=setup");
break;
case 'setup':
$conf = read_config(CONFIG);
$conf = setup($conf);
if (isset($conf)) {
write_config(CONFIG, $conf);
header("Location: {$_SERVER['SCRIPT_NAME']}?action=setup");
}
break;
case 'rrd':
$conf = read_config(CONFIG);
show_rrd($conf);
break;
default:
case 'show':
$conf = read_config(CONFIG);
show_html($conf);
break;
}
?>

151
signals.c
View File

@ -1,151 +0,0 @@
/***************************************************************************
* Copyright (C) 05/2009 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include "event.h"
#include "list.h"
#include "logging.h"
#include "signals.h"
struct signal_entry {
struct list_head list;
int signum;
int deleted;
void (*callback)(void *privdata);
void *privdata;
};
static LIST_HEAD(callback_list);
static int sig_pipe[2];
static void sig_handler(int signal)
{
unsigned char signum = (signal & 0xFF);
write(sig_pipe[1], &signum, 1);
}
int signal_remove_callback(int signum, int type)
{
/* mark all old handler for deletion */
struct signal_entry *search;
list_for_each_entry(search, &callback_list, list) {
if (search->signum == signum)
search->deleted = 1;
}
struct sigaction sig_action;
switch (type) {
case SIG_IGNORE:
sig_action.sa_handler = SIG_IGN;
break;
default:
case SIG_DEFAULT:
sig_action.sa_handler = SIG_DFL;
break;
}
if (sigaction(signum, &sig_action, NULL) < 0) {
log_print(LOG_WARN, "%s(): sigaction(%d)", __FUNCTION__, signum);
return -1;
}
/* trigger remove */
sig_handler(0);
return 0;
}
int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata)
{
struct signal_entry *entry = malloc(sizeof(struct signal_entry));
if (entry == NULL) {
log_print(LOG_WARN, "%s(): out of memory", __FUNCTION__);
return -1;
}
entry->signum = signum;
entry->deleted = 0;
entry->callback = callback;
entry->privdata = privdata;
list_add_tail(&entry->list, &callback_list);
struct sigaction sig_action = {
.sa_handler = sig_handler,
};
if (sigaction(signum, &sig_action, NULL) < 0) {
log_print(LOG_WARN, "%s(): sigaction(%d)", __FUNCTION__, signum);
list_del(&entry->list);
free(entry);
return -1;
}
return 0;
}
static int sig_event(int fd, void *privdata)
{
unsigned char signum;
int len = read(fd, &signum, 1);
if (len <= 0) {
log_print(LOG_WARN, "%s(): read()", __FUNCTION__);
return -1;
}
struct signal_entry *search, *tmp;
list_for_each_entry_safe(search, tmp, &callback_list, list) {
if (search->deleted) {
list_del(&search->list);
free(search);
continue;
}
if (search->signum == signum)
search->callback(search->privdata);
}
return 0;
}
int signal_init(void)
{
if (pipe(sig_pipe) < 0) {
log_print(LOG_ERROR, "%s(): pipe()", __FUNCTION__);
return -1;
}
if (fcntl(sig_pipe[0], F_SETFD, FD_CLOEXEC) < 0) {
log_print(LOG_WARN, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
return -1;
}
if (fcntl(sig_pipe[1], F_SETFD, FD_CLOEXEC) < 0) {
log_print(LOG_WARN, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
return -1;
}
event_add_readfd(NULL, sig_pipe[0], sig_event, NULL);
return 0;
}

View File

@ -1,12 +0,0 @@
#ifndef _SIGNALS_H
#define _SIGNALS_H
#define SIG_DEFAULT 0x00
#define SIG_IGNORE 0x01
int signal_remove_callback(int signum, int type);
int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata);
int signal_init(void);
#endif // _SIGNALS_H

View File

@ -1,117 +0,0 @@
/***************************************************************************
* Copyright (C) 07/2007 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int parse_sockaddr(const char *addr, struct sockaddr_in *sa)
{
char *buf = strdup(addr);
if (buf == NULL)
return -1;
char *tmp;
char *ipstr = strtok_r(buf, ":", &tmp);
if (ipstr == NULL) {
free(buf);
return -2;
}
sa->sin_family = AF_INET;
if (inet_pton(AF_INET, ipstr, &sa->sin_addr) <= 0) {
free(buf);
return -3;
}
char *portstr = strtok_r(NULL, " \r\n", &tmp);
if (portstr == NULL) {
free(buf);
return -4;
}
int port = atoi(portstr);
if (port < 0 || port > 65535) {
free(buf);
return -5;
}
sa->sin_port = htons(port);
free(buf);
return 0;
}
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask)
{
char *buf = strdup(addr);
if (buf == NULL)
return -1;
char *tmp;
char *netstr = strtok_r(buf, "/", &tmp);
if (netstr == NULL) {
free(buf);
return -2;
}
if (inet_pton(AF_INET, netstr, net) <= 0) {
free(buf);
return -3;
}
char *maskstr = strtok_r(NULL, " \r\n", &tmp);
if (maskstr == NULL) {
mask->s_addr = ~0;
} else if (inet_pton(AF_INET, maskstr, mask) <= 0) {
int maskbits = atoi(maskstr);
if (maskbits < 0 || maskbits > 32) {
free(buf);
return -4;
}
mask->s_addr = htonl(~0 << (32 - maskbits));
}
free(buf);
return 0;
}
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr)
{
return snprintf(buf, size, "%s:%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
}
char * get_sockaddr_buf(struct sockaddr_in *addr)
{
static char ret[24];
get_sockaddr(ret, sizeof(ret), addr);
return ret;
}
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b)
{
return !((a->sin_family ^ b->sin_family) |
(a->sin_addr.s_addr ^ b->sin_addr.s_addr) |
(a->sin_port ^ b->sin_port));
}

View File

@ -1,14 +0,0 @@
#ifndef _SOCKADDR_H_
#define _SOCKADDR_H_
#include <netinet/in.h>
int parse_sockaddr(const char *addr, struct sockaddr_in *sa);
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask);
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr);
char * get_sockaddr_buf(struct sockaddr_in *addr);
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b);
#endif /* _SOCKADDR_H_ */