Commit c4be5806 authored by Geoff Simmons's avatar Geoff Simmons

trackrdrd: Added configuration via config file

parent 58365a5f
......@@ -8,7 +8,8 @@ trackrdrd_SOURCES = \
trackrdrd.h \
trackrdrd.c \
parse.c \
log.c
log.c \
config.c
trackrdrd_LDADD = \
$(VARNISHSRC)/lib/libvarnishcompat/libvarnishcompat.la \
......
/*-
* Copyright (c) 2012 UPLEX Nils Goroll Systemoptimierung
* Copyright (c) 2012 Otto Gmbh & Co KG
* All rights reserved
* Use only with permission
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <syslog.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include "trackrdrd.h"
#include "libvarnish.h"
static const int facilitynum[8] =
{ LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5,
LOG_LOCAL6, LOG_LOCAL7 };
static int
conf_getFacility(const char *facility) {
int localnum;
if (strcasecmp(facility, "USER") == 0)
return LOG_USER;
if (strlen(facility) != 6
|| strncasecmp(facility, "LOCAL", 5) != 0
|| !isdigit(facility[5]))
return(-1);
localnum = atoi(&facility[5]);
if (localnum > 7)
return(-1);
return(facilitynum[localnum]);
}
static int
conf_getUnsignedInt(const char *rval, unsigned *i)
{
long n;
char *p;
errno = 0;
n = strtoul(rval, &p, 10);
if (errno)
return(errno);
if (strlen(p) != 0)
return(EINVAL);
if (n < 0 || n > UINT_MAX)
return(ERANGE);
*i = (unsigned int) n;
return(0);
}
#define confString(name,fld) \
if (strcmp(lval, (name)) == 0) { \
strcpy((config.fld), rval); \
return(0); \
}
#define confUnsigned(name,fld) \
if (strcmp(lval, name) == 0) { \
unsigned int i; \
int err = conf_getUnsignedInt(rval, &i); \
if (err != 0) \
return err; \
config.fld = i; \
return(0); \
}
int
CONF_Add(const char *lval, const char *rval)
{
int ret;
confString("pid.file", pid_file);
confString("varnish.name", varnish_name);
confString("log.file", log_file);
confString("varnish.bindump", varnish_bindump);
confString("processor.log", processor_log);
confUnsigned("maxopen.scale", maxopen_scale);
confUnsigned("maxdata.scale", maxdata_scale);
if (strcmp(lval, "syslog.facility") == 0) {
if ((ret = conf_getFacility(rval)) < 0)
return EINVAL;
config.syslog_facility = ret;
strcpy(config.syslog_facility_name, rval);
char *p = &config.syslog_facility_name[0];
do { *p = toupper(*p); } while (*++p);
return(0);
}
if (strcmp(lval, "monitor.interval") == 0) {
char *p;
errno = 0;
double d = strtod(rval, &p);
if (errno)
return(errno);
if (strlen(p) != 0 || d < 0 || !isfinite(d))
return(EINVAL);
config.monitor_interval = d;
return(0);
}
return EINVAL;
}
static int
conf_ParseLine(char *ptr, char **lval, char **rval)
{
char *endlval;
*lval = ptr;
while(*++ptr && !isspace(*ptr) && *ptr != '=')
;
if (*ptr == '\0')
return(1);
endlval = ptr;
while(isspace(*ptr) && *++ptr)
;
if (ptr == '\0' || *ptr != '=')
return(1);
while(*++ptr && isspace(*ptr))
;
if (ptr == '\0')
return(1);
*endlval = '\0';
*rval = ptr;
return(0);
}
void
CONF_Init(void)
{
strcpy(config.pid_file, "/var/run/trackrdrd.pid");
config.varnish_name[0] = '\0';
config.log_file[0] = '\0';
config.varnish_bindump[0] = '\0';
config.syslog_facility = LOG_LOCAL0;
config.monitor_interval = 30;
config.processor_log[0] = '\0';
config.maxopen_scale = 0;
config.maxdata_scale = 0;
}
int
CONF_ReadFile(const char *file) {
FILE *in;
char line[BUFSIZ];
int linenum = 0;
in = fopen(file, "r");
if (in == NULL) {
perror(file);
return(-1);
}
while (fgets(line, BUFSIZ, in) != NULL) {
char orig[BUFSIZ];
linenum++;
char *comment = strchr(line, '#');
if (comment != NULL)
*comment = '\0';
if (strlen(line) == 0)
continue;
char *ptr = line + strlen(line) - 1;
while (ptr != line && isspace(*ptr))
--ptr;
ptr[isspace(*ptr) ? 0 : 1] = '\0';
if (strlen(line) == 0)
continue;
ptr = line;
while (isspace(*ptr) && *++ptr)
;
strcpy(orig, ptr);
char *lval, *rval;
if (conf_ParseLine(ptr, &lval, &rval) != 0) {
fprintf(stderr, "Cannot parse %s line %d: '%s'\n", file, linenum,
orig);
return(-1);
}
int ret;
if ((ret = CONF_Add((const char *) lval, (const char *) rval)) != 0) {
fprintf(stderr, "Error in %s line %d (%s): '%s'\n", file, linenum,
strerror(ret), orig);
return(-1);
}
}
return(0);
}
#define confdump(str,val) \
LOG_Log(LOG_DEBUG, "config: " str, (val))
void
CONF_Dump(void)
{
confdump("pid.file = %s", config.pid_file);
confdump("varnish.name = %s", config.varnish_name);
confdump("log.file = %s",
strcmp(config.log_file,"-") == 0 ? "stdout" : config.log_file);
confdump("varnish.bindump = %s", config.varnish_bindump);
confdump("syslog.facility = %s", config.syslog_facility_name);
confdump("monitor.interval = %.1f", config.monitor_interval);
confdump("processor.log = %s", config.processor_log);
confdump("maxopen.scale = %d", config.maxopen_scale);
confdump("maxdata.scale = %d", config.maxdata_scale);
}
......@@ -52,22 +52,6 @@ syslog_setlevel(int level)
setlogmask(LOG_UPTO(level));
}
static int
syslog_getFacility(const char *facility) {
int localnum;
if (strcasecmp(facility, "USER") == 0)
return LOG_USER;
if (strlen(facility) != 6
|| strncasecmp(facility, "LOCAL", 5) != 0
|| !isdigit(facility[5]))
return(-1);
localnum = atoi(&facility[5]);
if (localnum > 7)
return(-1);
return(facilitynum[localnum]);
}
/* XXX: is this safe? */
static void
stdio_initnames(void)
......@@ -108,34 +92,26 @@ stdio_close(void)
fclose(logconf.out);
}
int LOG_Open(const char *progname, const char *dest, const char *facility)
int LOG_Open(const char *progname)
{
if (dest == NULL) {
if (EMPTY(config.log_file)) {
/* syslog */
int fac = LOG_LOCAL0;
if (facility != NULL) {
fac = syslog_getFacility(facility);
if (fac < 0) {
fprintf(stderr, "Invalid facility: %s\n", facility);
return(-1);
}
}
logconf.log = syslog;
logconf.setlevel = syslog_setlevel;
logconf.close = closelog;
openlog(progname, LOG_PID | LOG_CONS | LOG_NDELAY | LOG_NOWAIT, fac);
openlog(progname, LOG_PID | LOG_CONS | LOG_NDELAY | LOG_NOWAIT,
config.syslog_facility);
setlogmask(LOG_UPTO(LOG_INFO));
atexit(closelog);
return(0);
}
if (strcmp(dest, "-") == 0)
if (strcmp(config.log_file, "-") == 0)
logconf.out = stdout;
else {
logconf.out = fopen(dest, "w");
logconf.out = fopen(config.log_file, "a");
if (logconf.out == NULL) {
perror(dest);
perror(config.log_file);
return(-1);
}
}
......
......@@ -11,8 +11,8 @@
# logging to stdout in debug mode, and obtains a cksum from
# stdout. The cksum must match an expected value.
CKSUM=$(./trackrdrd -f test/varnish.binlog -l - -d | cksum)
if [ "$CKSUM" != '915150825 166426' ]; then
CKSUM=$(./trackrdrd -f test/varnish.binlog -l - -d -c test/test.conf | cksum)
if [ "$CKSUM" != '3004877510 166790' ]; then
echo "ERROR: Regression test incorrect cksum: $CKSUM"
exit 1
fi
......
# Test configuration for the varnish log tracking reader
log.file = /tmp/trackrdrd.log
pid.file = /tmp/trackrdrd.pid
processor.log = /tmp/rdrproc.log
......@@ -44,6 +44,7 @@
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/fcntl.h>
#include "compat/daemon.h"
......@@ -62,6 +63,8 @@
#define TRACKLOG_PREFIX "track "
#define TRACKLOG_PREFIX_LEN (sizeof(TRACKLOG_PREFIX)-1)
#define DEFAULT_CONFIG "/etc/trackrdrd.conf"
/*--------------------------------------------------------------------*/
static int
......@@ -190,20 +193,28 @@ int
main(int argc, char * const *argv)
{
int c;
int D_flag = 0, d_flag = 0;
int d_flag = 0;
const char *P_arg = NULL, *l_arg = NULL, *n_arg = NULL, *f_arg = NULL,
*y_arg = NULL;
*y_arg = NULL, *c_arg = NULL;
struct vpf_fh *pfh = NULL;
struct VSM_data *vd;
vd = VSM_New();
VSL_Setup(vd);
while ((c = getopt(argc, argv, "DP:Vn:hl:df:y:")) != -1) {
if (access(DEFAULT_CONFIG, F_OK) == 0) {
if (access(DEFAULT_CONFIG, R_OK) != 0) {
perror(DEFAULT_CONFIG);
exit(EXIT_FAILURE);
}
printf("Reading config from %s\n", DEFAULT_CONFIG);
if (CONF_ReadFile(DEFAULT_CONFIG) != 0)
exit(EXIT_FAILURE);
}
/* XXX: When we can demonize, add an option to run as non-demon */
while ((c = getopt(argc, argv, "P:Vn:hl:df:y:c:")) != -1) {
switch (c) {
case 'D':
D_flag = 1;
break;
case 'P':
P_arg = optarg;
break;
......@@ -225,6 +236,9 @@ main(int argc, char * const *argv)
case 'y':
y_arg = optarg;
break;
case 'c':
c_arg = optarg;
break;
case 'h':
usage(EXIT_SUCCESS);
default:
......@@ -235,42 +249,61 @@ main(int argc, char * const *argv)
if ((argc - optind) > 0)
usage(EXIT_FAILURE);
if (c_arg) {
printf("Reading config from %s\n", c_arg);
if (CONF_ReadFile(c_arg) != 0)
exit(EXIT_FAILURE);
}
if (f_arg && n_arg)
usage(EXIT_FAILURE);
if (l_arg && y_arg)
usage(EXIT_FAILURE);
if (P_arg)
strcpy(config.pid_file, P_arg);
if (n_arg)
strcpy(config.varnish_name, n_arg);
if (l_arg)
strcpy(config.log_file, l_arg);
if (y_arg)
CONF_Add("syslog.facility", y_arg);
if (f_arg && VSL_Arg(vd, 'r', f_arg) <= 0)
exit(EXIT_FAILURE);
else if (n_arg && VSL_Arg(vd, 'n', n_arg) <= 0)
else if (!EMPTY(config.varnish_name)
&& VSL_Arg(vd, 'n', config.varnish_name) <= 0)
exit(EXIT_FAILURE);
if (LOG_Open(PACKAGE_NAME, l_arg, y_arg) != 0) {
if (LOG_Open(PACKAGE_NAME) != 0) {
exit(EXIT_FAILURE);
}
if (d_flag)
LOG_SetLevel(LOG_DEBUG);
LOG_Log0(LOG_INFO, "starting");
/*
if (D_flag && varnish_daemon(0, 0) == -1) {
perror("daemon()");
if (pfh != NULL)
VPF_Remove(pfh);
exit(1);
}
*/
CONF_Dump();
/* XXX: Parent/child setup
Write the pid in the parent, open VSL in the child
*/
if (P_arg && (pfh = VPF_Open(P_arg, 0644, NULL)) == NULL) {
perror(P_arg);
if (!EMPTY(config.pid_file)
&& (pfh = VPF_Open(config.pid_file, 0644, NULL)) == NULL) {
perror(config.pid_file);
exit(EXIT_FAILURE);
}
if (pfh != NULL)
VPF_Write(pfh);
/*
if (!D_flag && varnish_daemon(0, 0) == -1) {
perror("daemon()");
if (pfh != NULL)
VPF_Remove(pfh);
exit(1);
}
*/
/* XXX: child opens and reads VSL */
if (VSL_Open(vd, 1))
exit(EXIT_FAILURE);
......
......@@ -31,6 +31,27 @@
#include <stdio.h>
#define EMPTY(s) (s[0] == '\0')
/* config.c */
struct config {
char pid_file[BUFSIZ];
char varnish_name[BUFSIZ];
char log_file[BUFSIZ];
char varnish_bindump[BUFSIZ];
int syslog_facility;
char syslog_facility_name[BUFSIZ];
double monitor_interval;
char processor_log[BUFSIZ];
unsigned maxopen_scale;
unsigned maxdata_scale;
} config;
void CONF_Init(void);
int CONF_Add(const char *lval, const char *rval);
int CONF_ReadFile(const char *file);
void CONF_Dump(void);
/* log.c */
typedef void log_log_t(int level, const char *msg, ...);
typedef void log_setlevel_t(int level);
......@@ -44,7 +65,7 @@ struct logconf {
int level;
} logconf;
int LOG_Open(const char *progname, const char *dest, const char *facility);
int LOG_Open(const char *progname);
/* XXX: __VA_ARGS__ can't be empty ... */
#define LOG_Log0(level, msg) logconf.log(level, msg)
#define LOG_Log(level, msg, ...) logconf.log(level, msg, __VA_ARGS__)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment