Compare commits

..

No commits in common. "master" and "0.3.3-rc1" have entirely different histories.

30 changed files with 133 additions and 313 deletions

3
.gitignore vendored
View file

@ -1,7 +1,8 @@
*~
# Binaries
/src/vzlogger
/bin/logger/vzlogger
/bin/reader/reader
# Compiled Object files
*.slo

2
debian/changelog vendored
View file

@ -1,4 +1,4 @@
vzlogger (0.3.3-1) stable; urgency=low
vzlogger (0.3.3-rc1) stable; urgency=low
* added support for new fluksometer
* some code refactoring & cleanup

View file

@ -39,13 +39,7 @@ typedef struct {
size_t size;
} CURLresponse;
typedef struct {
CURL *curl;
struct curl_slist *headers;
} api_handle_t;
int api_init(channel_t *ch, api_handle_t *api);
void api_free(api_handle_t *api);
CURL * api_curl_init(channel_t *ch);
/**
* Reformat CURLs debugging output
@ -67,6 +61,6 @@ json_object * api_json_tuples(buffer_t *buf, reading_t *first, reading_t *last);
/**
* Parses JSON encoded exception and stores describtion in err
*/
int api_parse_exception(CURLresponse response, char *err, size_t n);
void api_parse_exception(CURLresponse response, char *err, size_t n);
#endif /* _API_H_ */

View file

@ -50,7 +50,7 @@ reading_t * buffer_push(buffer_t *buf, reading_t *rd);
void buffer_free(buffer_t *buf);
void buffer_clean(buffer_t *buf);
void buffer_clear(buffer_t *buf);
char * buffer_dump(buffer_t *buf, char *dump, size_t len);
char * buffer_dump(buffer_t *buf, char *dump, int len);
#endif /* _BUFFER_H_ */

View file

@ -41,6 +41,7 @@ typedef struct channel {
pthread_cond_t condition; /* pthread syncronization to notify logging thread and local webserver */
pthread_t thread; /* pthread for asynchronus logging */
pthread_status_t status; /* status of thread */
char *middleware; /* url to middleware */
char *uuid; /* unique identifier for middleware */

View file

@ -91,7 +91,6 @@ typedef struct {
/* function pointers */
int (*init_func)(meter_t *mtr, list_t options);
void (*free_func)(meter_t *mtr);
int (*open_func)(meter_t *mtr);
int (*close_func)(meter_t *mtr);
size_t (*read_func)(meter_t *mtr, reading_t *rds, size_t n);

View file

@ -47,7 +47,6 @@ struct meter;
struct reading;
int meter_init_d0(struct meter *mtr, list_t options);
void meter_free_d0(struct meter *mtr);
int meter_open_d0(struct meter *mtr);
int meter_close_d0(struct meter *mtr);
size_t meter_read_d0(struct meter *mtr, struct reading *rds, size_t n);
@ -61,6 +60,4 @@ size_t meter_read_d0(struct meter *mtr, struct reading *rds, size_t n);
*/
int meter_d0_open_socket(const char *node, const char *service);
int meter_d0_open_device(const char *device, struct termios *old_tio, speed_t baudrate);
#endif /* _D0_H_ */

View file

@ -38,7 +38,6 @@ struct meter;
struct reading;
int meter_init_exec(struct meter *mtr, list_t options);
void meter_free_exec(struct meter *mtr);
int meter_open_exec(struct meter *mtr);
int meter_close_exec(struct meter *mtr);
size_t meter_read_exec(struct meter *mtr, struct reading *rds, size_t n);

View file

@ -41,7 +41,6 @@ struct meter;
struct reading;
int meter_init_file(struct meter *mtr, list_t options);
void meter_free_file(struct meter *mtr);
int meter_open_file(struct meter *mtr);
int meter_close_file(struct meter *mtr);
size_t meter_read_file(struct meter *mtr, struct reading *rds, size_t n);

View file

@ -26,8 +26,6 @@
#ifndef _FLUKSOV2_H_
#define _FLUKSOV2_H_
#define FLUKSOV2_DEFAULT_FIFO "/var/run/spid/delta/out"
typedef struct {
char *fifo;
@ -39,7 +37,6 @@ struct meter;
struct reading;
int meter_init_fluksov2(struct meter *mtr, list_t options);
void meter_free_fluksov2(struct meter *mtr);
int meter_open_fluksov2(struct meter *mtr);
int meter_close_fluksov2(struct meter *mtr);
size_t meter_read_fluksov2(struct meter *mtr, struct reading *rds, size_t n);

View file

@ -38,7 +38,6 @@ struct reading;
double ltqnorm(double p);
int meter_init_random(struct meter *mtr, list_t options);
void meter_free_random(struct meter *mtr);
int meter_open_random(struct meter *mtr);
int meter_close_random(struct meter *mtr);
size_t meter_read_random(struct meter *mtr, struct reading *rds, size_t n);

View file

@ -41,7 +41,6 @@ struct meter;
struct reading;
int meter_init_s0(struct meter *mtr, list_t options);
void meter_free_s0(struct meter *mtr);
int meter_open_s0(struct meter *mtr);
int meter_close_s0(struct meter *mtr);
size_t meter_read_s0(struct meter *mtr, struct reading *rds, size_t n);

View file

@ -61,13 +61,6 @@ struct reading;
*/
int meter_init_sml(struct meter *mtr, list_t options);
/**
* Freeing allocated resources during initialization
*
* @param mtr the meter structure
*/
void meter_free_sml(struct meter *mtr);
/**
* Open connection via serial port or socket to meter
*

View file

@ -51,20 +51,12 @@ typedef struct reading {
enum meter_procotol; /* forward declaration */
/**
* Manages memory for string identifiers
*
* @param str string to lookup in the registry
* @return pointer to string in the regstry
*/
char * reading_id_registry(const char *str);
/**
* Parse two reading identifiers in a given protocol context
*
* @return result like in strcmp()
*/
int reading_id_compare(enum meter_procotol prot, reading_id_t a, reading_id_t b);
int meter_id_compare(enum meter_procotol, reading_id_t a, reading_id_t b);
/**
* Parse identifier by a given string and protocol

View file

@ -35,6 +35,14 @@
#include "common.h"
#include "list.h"
/* enumerations */
typedef enum {
status_unknown,
status_running,
status_terminated,
status__cancelled
} pthread_status_t;
/**
* Type for mapping channels to meters
*/
@ -43,6 +51,7 @@ typedef struct map {
list_t channels;
pthread_t thread;
pthread_status_t status;
} map_t;
/* prototypes */

View file

@ -107,65 +107,59 @@ json_object * api_json_tuples(buffer_t *buf, reading_t *first, reading_t *last)
return json_tuples;
}
int api_init(channel_t *ch, api_handle_t *api) {
CURL * api_curl_init(channel_t *ch) {
CURL *curl;
struct curl_slist *header = NULL;
char url[255], agent[255];
/* prepare header, uuid & url */
sprintf(agent, "User-Agent: %s/%s (%s)", PACKAGE, VERSION, curl_version()); /* build user agent */
sprintf(url, "%s/data/%s.json", ch->middleware, ch->uuid); /* build url */
api->headers = NULL;
api->headers = curl_slist_append(api->headers, "Content-type: application/json");
api->headers = curl_slist_append(api->headers, "Accept: application/json");
api->headers = curl_slist_append(api->headers, agent);
header = curl_slist_append(header, "Content-type: application/json");
header = curl_slist_append(header, "Accept: application/json");
header = curl_slist_append(header, agent);
api->curl = curl_easy_init();
if (!api->curl) {
return EXIT_FAILURE;
curl = curl_easy_init();
if (!curl) {
print(log_error, "CURL: cannot create handle", ch);
exit(EXIT_FAILURE);
}
curl_easy_setopt(api->curl, CURLOPT_URL, url);
curl_easy_setopt(api->curl, CURLOPT_HTTPHEADER, api->headers);
curl_easy_setopt(api->curl, CURLOPT_VERBOSE, options.verbosity);
curl_easy_setopt(api->curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback);
curl_easy_setopt(api->curl, CURLOPT_DEBUGDATA, (void *) ch);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_VERBOSE, options.verbosity);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *) ch);
return EXIT_SUCCESS;
return curl;
}
void api_free(api_handle_t *api) {
curl_easy_cleanup(api->curl);
curl_slist_free_all(api->headers);
}
int api_parse_exception(CURLresponse response, char *err, size_t n) {
void api_parse_exception(CURLresponse response, char *err, size_t n) {
struct json_tokener *json_tok;
struct json_object *json_obj;
json_tok = json_tokener_new();
json_obj = json_tokener_parse_ex(json_tok, response.data, response.size);
if (json_tok->err != json_tokener_success) {
json_tokener_free(json_tok);
return ERR;
}
if (json_tok->err == json_tokener_success) {
json_obj = json_object_object_get(json_obj, "exception");
json_obj = json_object_object_get(json_obj, "exception");
if (json_obj) {
snprintf(err, n, "%s: %s",
json_object_get_string(json_object_object_get(json_obj, "type")),
json_object_get_string(json_object_object_get(json_obj, "message"))
);
if (json_obj) {
snprintf(err, n, "%s: %s",
json_object_get_string(json_object_object_get(json_obj, "type")),
json_object_get_string(json_object_object_get(json_obj, "message"))
);
}
else {
strncpy(err, "missing exception", n);
}
}
else {
json_object_put(json_obj);
json_tokener_free(json_tok);
return ERR;
strncpy(err, json_tokener_errors[json_tok->err], n);
}
json_object_put(json_obj);
json_tokener_free(json_tok);
return SUCCESS;
}

View file

@ -97,32 +97,26 @@ void buffer_clean(buffer_t *buf) {
pthread_mutex_unlock(&buf->mutex);
}
char * buffer_dump(buffer_t *buf, char *dump, size_t len) {
size_t pos = 0;
dump[pos++] = '{';
char * buffer_dump(buffer_t *buf, char *dump, int len) {
strcpy(dump, "|");
for (reading_t *rd = buf->head; rd != NULL; rd = rd->next) {
if (pos < len) {
pos += snprintf(dump+pos, len-pos, "%.2f", rd->value);
}
char tmp[16];
sprintf(tmp, "%.2f|", rd->value);
/* indicate last sent reading */
if (pos < len && buf->sent == rd) {
dump[pos++] = '!';
}
if (strlen(dump)+strlen(tmp) < len) {
if (buf->sent == rd) { /* indicate last sent reading */
strcat(dump, "!");
}
/* add seperator between values */
if (pos < len && rd->next != NULL) {
dump[pos++] = ',';
strcat(dump, tmp);
}
else {
return NULL; /* dump buffer is full! */
}
}
if (pos+1 < len) {
dump[pos++] = '}';
dump[pos] = '\0'; /* zero terminated string */
}
return (pos < len) ? dump : NULL; /* buffer full? */
return dump;
}
void buffer_free(buffer_t *buf) {

View file

@ -35,6 +35,7 @@ void channel_init(channel_t *ch, const char *uuid, const char *middleware, readi
snprintf(ch->id, 5, "ch%i", instances++);
ch->identifier = identifier;
ch->status = status_unknown;
ch->uuid = strdup(uuid);
ch->middleware = strdup(middleware);

View file

@ -29,19 +29,19 @@
#include "meter.h"
#include "options.h"
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME, meter_free_##NAME, meter_open_##NAME, meter_close_##NAME, meter_read_##NAME }
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME, meter_open_##NAME, meter_close_##NAME, meter_read_##NAME }
static const meter_details_t protocols[] = {
/* alias description max_rds periodic
===============================================================================================*/
METER_DETAIL(file, "Read from file or fifo", 32, TRUE),
//METER_DETAIL(exec, "Parse program output", 32, TRUE),
METER_DETAIL(random, "Generate random values with a random walk", 1, TRUE),
METER_DETAIL(fluksov2, "Read from Flukso's onboard SPI fifo", 16, FALSE),
METER_DETAIL(s0, "S0-meter directly connected to RS232", 1, TRUE),
METER_DETAIL(d0, "DLMS/IEC 62056-21 plaintext protocol", 32, FALSE),
METER_DETAIL(file, "Read from file (ex. 1-Wire sensors via OWFS)", 32, TRUE),
//METER_DETAIL(exec, "Read from program (ex. 1-Wire sensors via digitemp)", 32, TRUE),
METER_DETAIL(random, "Random walk", 1, TRUE),
METER_DETAIL(fluksov2, "Read from onboard SPI of a Flukso v2", 16, FALSE),
METER_DETAIL(s0, "S0 on RS232", 1, TRUE),
METER_DETAIL(d0, "Plaintext protocol (DIN EN 62056-21)", 32, FALSE),
#ifdef SML_SUPPORT
METER_DETAIL(sml, "Smart Message Language as used by EDL-21, eHz and SyM²", 32, FALSE),
METER_DETAIL(sml, "Smart Meter Language", 32, FALSE),
#endif /* SML_SUPPORT */
{} /* stop condition for iterator */
};
@ -77,9 +77,14 @@ int meter_init(meter_t *mtr, list_t options) {
return details->init_func(mtr, options);
}
void meter_free(meter_t *mtr) {
const meter_details_t *details = meter_get_details(mtr->protocol);
return details->free_func(mtr);
int meter_lookup_protocol(const char* name, meter_protocol_t *protocol) {
for (const meter_details_t *it = meter_get_protocols(); it != NULL; it++) {
if (strcmp(it->name, name) == 0) {
*protocol = it->id;
return SUCCESS;
}
}
return ERR_NOT_FOUND;
}
int meter_open(meter_t *mtr) {
@ -97,16 +102,6 @@ size_t meter_read(meter_t *mtr, reading_t rds[], size_t n) {
return details->read_func(mtr, rds, n);
}
int meter_lookup_protocol(const char* name, meter_protocol_t *protocol) {
for (const meter_details_t *it = meter_get_protocols(); it != NULL; it++) {
if (strcmp(it->name, name) == 0) {
*protocol = it->id;
return SUCCESS;
}
}
return ERR_NOT_FOUND;
}
const meter_details_t * meter_get_protocols() {
return protocols;
}

View file

@ -36,7 +36,6 @@
#include <errno.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/ioctl.h>
/* socket */
#include <netdb.h>
@ -99,23 +98,12 @@ int meter_init_d0(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_d0(meter_t *mtr) {
meter_handle_d0_t *handle = &mtr->handle.d0;
if (handle->device != NULL) {
free(handle->device);
}
if (handle->host != NULL) {
free(handle->host);
}
}
int meter_open_d0(meter_t *mtr) {
meter_handle_d0_t *handle = &mtr->handle.d0;
if (handle->device != NULL) {
handle->fd = meter_d0_open_device(handle->device, &handle->oldtio, handle->baudrate);
print(log_error, "TODO: implement serial interface", mtr);
return ERR;
}
else if (handle->host != NULL) {
char *addr = strdup(handle->host);
@ -304,35 +292,3 @@ int meter_d0_open_socket(const char *node, const char *service) {
return fd;
}
int meter_d0_open_device(const char *device, struct termios *old_tio, speed_t baudrate) {
struct termios tio;
memset(&tio, 0, sizeof(struct termios));
int fd = open(device, O_RDWR);
if (fd < 0) {
print(log_error, "open(%s): %s", NULL, device, strerror(errno));
return ERR;
}
/* get old configuration */
tcgetattr(fd, &tio) ;
/* backup old configuration to restore it when closing the meter connection */
memcpy(old_tio, &tio, sizeof(struct termios));
/* set 7-N-1 */
tio.c_iflag &= ~(BRKINT | INLCR | IMAXBEL);
tio.c_oflag &= ~(OPOST | ONLCR);
tio.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO);
tio.c_cflag |= (CS7 | PARENB);
/* set baudrate */
cfsetispeed(&tio, baudrate);
cfsetospeed(&tio, baudrate);
/* apply new configuration */
tcsetattr(fd, TCSANOW, &tio);
return fd;
}

View file

@ -62,16 +62,6 @@ int meter_init_exec(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_exec(meter_t *mtr) {
meter_handle_exec_t *handle = &mtr->handle.exec;
free(handle->command);
if (handle->format != NULL) {
free(handle->format);
}
}
int meter_open_exec(meter_t *mtr) {
//meter_handle_exec_t *handle = &mtr->handle.exec;

View file

@ -126,16 +126,6 @@ int meter_init_file(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_file(meter_t *mtr) {
meter_handle_file_t *handle = &mtr->handle.file;
free(handle->path);
if (handle->format != NULL) {
free(handle->format);
}
}
int meter_open_file(meter_t *mtr) {
meter_handle_file_t *handle = &mtr->handle.file;

View file

@ -41,18 +41,12 @@ int meter_init_fluksov2(meter_t *mtr, list_t options) {
handle->fifo = strdup(fifo);
}
else {
handle->fifo = strdup(FLUKSOV2_DEFAULT_FIFO); /* use default path */
handle->fifo = "/var/run/spid/delta/out"; /* use default path */
}
return SUCCESS;
}
void meter_free_fluksov2(meter_t *mtr) {
meter_handle_fluksov2_t *handle = &mtr->handle.fluksov2;
free(handle->fifo);
}
int meter_open_fluksov2(meter_t *mtr) {
meter_handle_fluksov2_t *handle = &mtr->handle.fluksov2;

View file

@ -55,10 +55,6 @@ int meter_init_random(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_random(meter_t *mtr) {
//meter_handle_random_t *handle = &mtr->handle.random;
}
int meter_open_random(meter_t *mtr) {
//meter_handle_random_t *handle = &mtr->handle.random;

View file

@ -59,12 +59,6 @@ int meter_init_s0(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_s0(meter_t *mtr) {
meter_handle_s0_t *handle = &mtr->handle.s0;
free(handle->device);
}
int meter_open_s0(meter_t *mtr) {
meter_handle_s0_t *handle = &mtr->handle.s0;

View file

@ -104,18 +104,6 @@ int meter_init_sml(meter_t *mtr, list_t options) {
return SUCCESS;
}
void meter_free_sml(meter_t *mtr) {
meter_handle_sml_t *handle = &mtr->handle.sml;
if (handle->device != NULL) {
free(handle->device);
}
if (handle->host != NULL) {
free(handle->host);
}
}
int meter_open_sml(meter_t *mtr) {
meter_handle_sml_t *handle = &mtr->handle.sml;

View file

@ -25,32 +25,10 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "reading.h"
#include "meter.h"
char * reading_id_registry(const char *str) {
static list_t strings;
char *found = NULL;
/* linear search in string list */
foreach(strings, it, const char *) {
if (strcmp(*it, str) == 0) {
found = *it;
break;
}
}
if (!found) {
found = strdup(str);
list_push(&strings, found);
}
return found;
}
int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b) {
switch (protocol) {
case meter_protocol_d0:
@ -62,10 +40,7 @@ int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b
case meter_protocol_file:
case meter_protocol_exec:
/* we only need to compare the base pointers here,
because each identifer exists only once in the registry
and has therefore a unique pointer */
return !(a.string == b.string);
return strcmp(a.string, b.string);
default:
/* no channel id, adding all readings to buffer */
@ -106,7 +81,7 @@ int reading_id_parse(meter_protocol_t protocol, reading_id_t *id, const char *st
case meter_protocol_file:
case meter_protocol_exec:
id->string = reading_id_registry(string);
id->string = strdup(string); // TODO free() elsewhere
break;
default: /* ignore other protocols which do not provide id's */

View file

@ -120,22 +120,9 @@ void * reading_thread(void *arg) {
/* debugging */
if (options.verbosity >= log_debug) {
size_t dump_len = 24;
char *dump = malloc(dump_len);
if (dump == NULL) {
print(log_error, "cannot allocate buffer", ch);
}
while (dump == NULL || buffer_dump(buf, dump, dump_len) == NULL) {
dump_len *= 1.5;
free(dump);
dump = malloc(dump_len);
}
print(log_debug, "Buffer dump (size=%i keep=%i): %s", ch, buf->size, buf->keep, dump);
free(dump);
char dump[1024];
buffer_dump(buf, dump, 1024);
print(log_debug, "Buffer dump: %s (size=%i, keep=%i)", ch, dump, buf->size, buf->keep);
}
}
@ -151,21 +138,14 @@ void * reading_thread(void *arg) {
}
void logging_thread_cleanup(void *arg) {
api_handle_t *api = (api_handle_t *) arg;
api_free(api);
curl_easy_cleanup((CURL *) arg); /* always cleanup */
}
void * logging_thread(void *arg) {
channel_t *ch = (channel_t *) arg; /* casting argument */
api_handle_t api;
if (api_init(ch, &api) != SUCCESS) {
print(log_error, "CURL: cannot create handle", ch);
exit(EXIT_FAILURE);
}
pthread_cleanup_push(&logging_thread_cleanup, &api);
CURL *curl = api_curl_init(ch);
pthread_cleanup_push(&logging_thread_cleanup, curl);
do { /* start thread mainloop */
CURLresponse response;
@ -191,30 +171,28 @@ void * logging_thread(void *arg) {
print(log_debug, "JSON request body: %s", ch, json_str);
curl_easy_setopt(api.curl, CURLOPT_POSTFIELDS, json_str);
curl_easy_setopt(api.curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback);
curl_easy_setopt(api.curl, CURLOPT_WRITEDATA, (void *) &response);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &response);
curl_code = curl_easy_perform(api.curl);
curl_easy_getinfo(api.curl, CURLINFO_RESPONSE_CODE, &http_code);
curl_code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
/* check response */
if (curl_code != CURLE_OK) {
print(log_error, "CURL: %s", ch, curl_easy_strerror(curl_code));
}
else if (http_code != 200) {
char exception[255];
if (api_parse_exception(response, exception, 255) == SUCCESS) {
print(log_error, "Request failed: [%i] %s", ch, http_code, exception);
}
else {
print(log_error, "Request failed: %i", ch, http_code);
}
}
else {
print(log_debug, "Request succeeded: %i", ch, http_code);
if (curl_code == CURLE_OK && http_code == 200) { /* everything is ok */
print(log_debug, "Request succeeded with code: %i", ch, http_code);
ch->buffer.sent = last->next;
}
else { /* error */
if (curl_code != CURLE_OK) {
print(log_error, "CURL: %s", ch, curl_easy_strerror(curl_code));
}
else if (http_code != 200) {
char err[255];
api_parse_exception(response, err, 255);
print(log_error, "Error from middleware: %s", ch, err);
}
}
/* householding */
free(response.data);

BIN
src/vzlogger Executable file

Binary file not shown.

View file

@ -94,48 +94,48 @@ const char *long_options_descs[] = {
* @param id could be NULL for general messages
* @todo integrate into syslog
*/
void print(log_level_t level, const char *format, void *id, ... ) {
void print(int level, const char *format, void *id, ... ) {
va_list args;
if (level > options.verbosity) {
return; /* skip message if its under the verbosity level */
}
struct timeval now;
struct tm * timeinfo;
char prefix[24];
size_t pos = 0;
char buffer[1024];
char *pos = buffer;
gettimeofday(&now, NULL);
timeinfo = localtime(&now.tv_sec);
/* format timestamp */
pos += strftime(prefix+pos, 18, "[%b %d %H:%M:%S]", timeinfo);
/* print timestamp to buffer */
pos += sprintf(pos, "[");
pos += strftime(pos, 16, "%b %d %H:%M:%S", timeinfo);
/* format section */
if (id) {
snprintf(prefix+pos, 8, "[%s]", (char *) id);
/* print logging 'section' */
pos += (id != NULL) ? sprintf(pos, "][%s]", (char *) id) : sprintf(pos, "]");
/* fill with whitespaces */
while(pos - buffer < 24) {
pos += sprintf(pos, " ");
}
va_list args;
/* print formatstring */
va_start(args, id);
/* print to stdout/stderr */
if (getppid() != 1) { /* running as fork in background? */
FILE *stream = (level > 0) ? stdout : stderr;
fprintf(stream, "%-24s", prefix);
vfprintf(stream, format, args);
fprintf(stream, "\n");
}
pos += vsprintf(pos, format, args);
va_end(args);
va_start(args, id);
/* print to stdout/stderr */
if (getppid() != 1) {
fprintf((level > 0) ? stdout : stderr, "%s\n", buffer);
}
/* append to logfile */
if (options.logfd) {
fprintf(options.logfd, "%-24s", prefix);
vfprintf(options.logfd, format, args);
fprintf(options.logfd, "\n");
fflush(options.logfd);
fprintf(options.logfd, "%s\n", buffer);
fflush(options.logfd);
}
va_end(args);
}
/**
@ -273,7 +273,6 @@ int config_parse_cli(int argc, char * argv[], config_options_t * options) {
break;
case 'c': /* config file */
free(options->config);
options->config = strdup(optarg);
break;
@ -307,8 +306,8 @@ int config_parse_cli(int argc, char * argv[], config_options_t * options) {
*/
int main(int argc, char *argv[]) {
/* default options */
options.config = strdup("/etc/vzlogger.conf");
options.log = NULL;
options.config = "/etc/vzlogger.conf";
options.log = "/var/log/vzlogger.log";
options.logfd = NULL;
options.port = 8080;
options.verbosity = 0;
@ -389,7 +388,7 @@ int main(int argc, char *argv[]) {
ch->buffer.keep = ceil(options.buffer_length / (double) mapping->meter.interval);
}
if (options.logging) {
if (ch->status != status_running && options.logging) {
pthread_create(&ch->thread, NULL, &logging_thread, (void *) ch);
print(log_debug, "Logging thread started", ch);
}
@ -423,10 +422,9 @@ int main(int argc, char *argv[]) {
channel_free(ch);
}
meter_close(mtr); /* closing connection */
list_free(&mapping->channels);
meter_free(mtr);
meter_close(mtr); /* closing connection */
}
#ifdef LOCAL_SUPPORT
@ -437,13 +435,11 @@ int main(int argc, char *argv[]) {
#endif /* LOCAL_SUPPORT */
/* householding */
free(options.config);
list_free(&mappings);
curl_global_cleanup();
/* close logfile */
if (options.logfd) {
free(options.log);
fclose(options.logfd);
}