1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

drop legacy logger

This commit is contained in:
Steffen Vogel 2021-02-16 14:15:38 +01:00
parent 7ebb902e25
commit 3a47bfa870
19 changed files with 81 additions and 1170 deletions

View file

@ -1,84 +0,0 @@
/** libcurl based advanced IO aka ADVIO.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLAScommon
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#include <cstdio>
#include <curl/curl.h>
#include <villas/utils.hpp>
#include <villas/exceptions.hpp>
struct advio {
CURL *curl;
FILE *file;
long uploaded; /**< Upload progress. How much has already been uploaded to the remote file. */
long downloaded; /**< Download progress. How much has already been downloaded from the remote file. */
int completed:1; /**< Was the upload completd */
unsigned char hash[SHA_DIGEST_LENGTH];
char mode[3];
char *uri;
};
typedef struct advio AFILE;
/* The remaining functions from stdio are just replaced macros */
#define afeof(af) feof((af)->file)
#define afgets(ln, sz, af) fgets(ln, sz, (af)->file)
#define aftell(af) ftell((af)->file)
#define afileno(af) fileno((af)->file)
#define afread(ptr, sz, nitems, af) fread(ptr, sz, nitems, (af)->file)
#define afwrite(ptr, sz, nitems, af) fwrite(ptr, sz, nitems, (af)->file)
#define afputs(ptr, af) fputs(ptr, (af)->file)
#define afprintf(af, fmt, ...) fprintf((af)->file, fmt, __VA_ARGS__)
#define afscanf(af, fmt, ...) fprintf((af)->file, fmt, __VA_ARGS__)
#define agetline(linep, linecapp, af) getline(linep, linecapp, (af)->file)
/* Extensions */
#define auri(af) ((af)->uri)
#define ahash(af) ((af)->hash)
/** Check if a URI is pointing to a local file. */
int aislocal(const char *uri);
AFILE *afopen(const char *url, const char *mode);
int afclose(AFILE *file);
int afflush(AFILE *file);
int afseek(AFILE *file, long offset, int origin);
void arewind(AFILE *file);
/** Download contens from remote file
*
* @param resume Do a partial download and append to the local file
*/
int adownload(AFILE *af, int resume);
int aupload(AFILE *af, int resume);

View file

@ -27,6 +27,8 @@
#include <jansson.h>
#include <villas/log.hpp>
#define HEIGHT (LOG_WIDTH - 55)
#define SEQ 17
@ -58,10 +60,10 @@ public:
double getStddev() const;
/** Print all statistical properties of distribution including a graphilcal plot of the histogram. */
void print(bool details) const;
void print(Logger logger, bool details) const;
/** Print ASCII style plot of histogram */
void plot() const;
void plot(Logger logger) const;
/** Dump histogram data in Matlab format.
*

View file

@ -123,8 +123,6 @@ void vlist_extend(struct vlist *l, size_t len, void *val);
/** Remove all elements for which the callback returns a non-zero return code. */
void vlist_filter(struct vlist *l, dtor_cb_t cb);
#include <villas/log.h>
/** Lookup an element from the list based on an UUID */
template<typename T>
T * vlist_lookup_uuid(struct vlist *l, uuid_t uuid)
@ -158,4 +156,4 @@ ssize_t vlist_lookup_index(struct vlist *l, const std::string &name)
return f ? vlist_index(l, f) : -1;
}
int vlist_init_and_push(struct vlist *l, void *p);
int vlist_init_and_push(struct vlist *l, void *p);

View file

@ -1,101 +0,0 @@
/** Logging and debugging routines
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLAScommon
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#include <cstdarg>
#include <jansson.h>
/* The log level which is passed as first argument to print() */
enum log_level {
LOG_LVL_DEBUG,
LOG_LVL_INFO,
LOG_LVL_WARN,
LOG_LVL_ERROR
};
/** Debug facilities.
*
* To be or-ed with the debug level
*/
enum log_facilities {
LOG_POOL = (1L << 8),
LOG_QUEUE = (1L << 9),
LOG_CONFIG = (1L << 10),
LOG_HOOK = (1L << 11),
LOG_PATH = (1L << 12),
LOG_NODE = (1L << 13),
LOG_MEM = (1L << 14),
LOG_WEB = (1L << 15),
LOG_API = (1L << 16),
LOG_LOG = (1L << 17),
LOG_VFIO = (1L << 18),
LOG_PCI = (1L << 19),
LOG_XIL = (1L << 20),
LOG_TC = (1L << 21),
LOG_IF = (1L << 22),
LOG_ADVIO = (1L << 23),
LOG_IO = (1L << 24),
/* Node-types */
LOG_SOCKET = (1L << 25),
LOG_FILE = (1L << 26),
LOG_FPGA = (1L << 27),
LOG_NGSI = (1L << 28),
LOG_WEBSOCKET = (1L << 29),
LOG_OPAL = (1L << 30),
LOG_COMEDI = (1L << 31),
LOG_IB = (1LL << 32),
/* Classes */
LOG_NODES = LOG_NODE | LOG_SOCKET | LOG_FILE | LOG_FPGA | LOG_NGSI | LOG_WEBSOCKET | LOG_OPAL | LOG_COMEDI | LOG_IB,
LOG_KERNEL = LOG_VFIO | LOG_PCI | LOG_TC | LOG_IF,
LOG_ALL = ~0xFF
};
int log_get_width();
/** Printf alike debug message with level. */
void debug(long long lvl, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
/** Printf alike info message. */
void info(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
/** Printf alike warning message. */
void warning(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
/** Print error and exit. */
void error(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
/** Print error and strerror(errno). */
void serror(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
/** Print configuration error and exit. */
void jerror(json_error_t *err, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));

View file

@ -65,7 +65,7 @@ public:
/**< Get the real usable log output width which fits into one line. */
int getWidth();
void parse(json_t *cfg);
void parse(json_t *json);
Logger get(const std::string &name);

View file

@ -110,7 +110,7 @@ public:
int load(const std::string &path);
int unload();
virtual int parse(json_t *cfg);
virtual int parse(json_t *json);
};
class Plugin {

View file

@ -30,6 +30,10 @@
#include <vector>
#include <string>
#include <villas/log.hpp>
namespace villas {
class Table;
class TableColumn {
@ -78,10 +82,13 @@ protected:
std::vector<TableColumn> columns;
Logger logger;
public:
Table(const std::vector<TableColumn> &cols) :
Table(Logger log, const std::vector<TableColumn> &cols) :
width(-1),
columns(cols)
columns(cols),
logger(log)
{ }
/** Print a table header consisting of \p n columns. */
@ -96,4 +103,6 @@ public:
}
};
} /* namespace villas */
/** @} */

View file

@ -40,7 +40,6 @@
#include <uuid/uuid.h>
#include <villas/config.h>
#include <villas/log.h>
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect((x),1)

View file

@ -21,30 +21,28 @@
##############################################################################
add_library(villas-common SHARED
advio.cpp
base64.cpp
buffer.cpp
common.cpp
compat.cpp
hist.cpp
cpuset.cpp
dsp/pid.cpp
hist.cpp
kernel/kernel.cpp
kernel/rt.cpp
list.cpp
log.cpp
log_legacy.cpp
memory.cpp
memory_manager.cpp
memory.cpp
plugin.cpp
popen.cpp
table.cpp
task.cpp
timing.cpp
utils.cpp
cpuset.cpp
terminal.cpp
version.cpp
common.cpp
timing.cpp
tool.cpp
base64.cpp
popen.cpp
utils.cpp
version.cpp
)
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)

View file

@ -1,508 +0,0 @@
/** libcurl based advanced IO aka ADVIO.
*
* This example requires libcurl 7.9.7 or later.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLAScommon
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#if __GNUC__ <= 7 && !defined(__clang__)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <filesystem>
namespace fs = std::filesystem;
#endif
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cerrno>
#include <unistd.h>
#include <curl/curl.h>
#include <villas/utils.hpp>
#include <villas/config.h>
#include <villas/advio.hpp>
using namespace villas;
using namespace villas::utils;
#define BAR_WIDTH 60 /**< How wide you want the progress meter to be. */
static int advio_trace(CURL * /* handle */, curl_infotype type, char *data, size_t size, void * /* userp */)
{
const char *text;
switch (type) {
case CURLINFO_TEXT:
text = "info";
break;
case CURLINFO_HEADER_OUT:
text = "send header";
break;
case CURLINFO_DATA_OUT:
text = "send data";
break;
case CURLINFO_HEADER_IN:
text = "recv header";
break;
case CURLINFO_DATA_IN:
text = "recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "recv SSL data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "send SSL data";
break;
default: /* in case a new one is introduced to shock us */
return 0;
}
debug(LOG_ADVIO | 5, "CURL: %s: %.*s", text, (int) size-1, data);
return 0;
}
static char * advio_human_time(double t, char *buf, size_t len)
{
unsigned i = 0;
const char *units[] = { "secs", "mins", "hrs", "days", "weeks", "months", "years" };
int divs[] = { 60, 60, 24, 7, 4, 12 };
while (i < ARRAY_LEN(divs) && t > divs[i]) {
t /= divs[i];
i++;
}
snprintf(buf, len, "%.2f %s", t, units[i]);
return buf;
}
static char * advio_human_size(double s, char *buf, size_t len)
{
unsigned i = 0;
const char *units[] = { "B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" };
while (s > 1024 && i < ARRAY_LEN(units)) {
s /= 1024;
i++;
}
snprintf(buf, len, "%.*f %s", i ? 2 : 0, s, units[i]);
return buf;
}
#if LIBCURL_VERSION_NUM >= 0x072000
static int advio_xferinfo(void *p, curl_off_t dl_total_bytes, curl_off_t dl_bytes, curl_off_t ul_total_bytes, curl_off_t ul_bytes)
{
struct advio *af = (struct advio *) p;
double cur_time, eta_time, estimated_time, frac;
curl_easy_getinfo(af->curl, CURLINFO_TOTAL_TIME, &cur_time);
/* Is this transaction an upload? */
int upload = ul_total_bytes > 0;
curl_off_t total_bytes = upload ? ul_total_bytes : dl_total_bytes;
curl_off_t bytes = upload ? ul_bytes : dl_bytes;
/* Are we finished? */
if (bytes == 0)
af->completed = 0;
if (af->completed)
return 0;
/* Ensure that the file to be downloaded is not empty
* because that would cause a division by zero error later on */
if (total_bytes <= 0)
return 0;
frac = (double) bytes / total_bytes;
estimated_time = cur_time * (1.0 / frac);
eta_time = estimated_time - cur_time;
/* Print file sizes in human readable format */
char buf[4][32];
char *bytes_human = advio_human_size(bytes, buf[0], sizeof(buf[0]));
char *total_bytes_human = advio_human_size(total_bytes, buf[1], sizeof(buf[1]));
char *eta_time_human = advio_human_time(eta_time, buf[2], sizeof(buf[2]));
/* Part of the progressmeter that's already "full" */
int dotz = round(frac * BAR_WIDTH);
/* Progress bar */
fprintf(stderr, "\r[");
for (int i = 0 ; i < BAR_WIDTH; i++) {
if (upload)
fputc(BAR_WIDTH - i > dotz ? ' ' : '<', stderr);
else
fputc(i > dotz ? ' ' : '>', stderr);
}
fprintf(stderr, "] ");
/* Details */
fprintf(stderr, "eta %-12s %12s of %-12s", eta_time_human, bytes_human, total_bytes_human);
fflush(stderr);
if (bytes == total_bytes) {
af->completed = 1;
fprintf(stderr, "\33[2K\r");
}
return 0;
}
#endif /* LIBCURL_VERSION_NUM >= 0x072000 */
int aislocal(const char *uri)
{
const char *sep;
const char *supported_schemas[] = { "file", "http", "https", "tftp", "ftp", "scp", "sftp", "smb", "smbs" };
sep = strstr(uri, "://");
if (!sep)
return 1; /* no schema, we assume its a local file */
for (unsigned i = 0; i < ARRAY_LEN(supported_schemas); i++) {
if (!strncmp(supported_schemas[i], uri, sep - uri))
return 0;
}
return -1; /* none of the supported schemas match. this is an invalid uri */
}
AFILE * afopen(const char *uri, const char *mode)
{
int ret;
const char *sep;
AFILE *af = new AFILE;
if (!af)
throw MemoryAllocationError();
memset(af, 0, sizeof(AFILE));
snprintf(af->mode, sizeof(af->mode), "%s", mode);
sep = strstr(uri, "://");
if (sep) {
af->uri = strdup(uri);
if (!af->uri)
goto out2;
}
else { /* Open local file by prepending file:// schema. */
if (strlen(uri) <= 1)
return nullptr;
/* Handle relative paths */
if (uri[0] != '/')
af->uri = strf("file://%s/%s", fs::current_path().c_str(), uri);
else
af->uri = strf("file://%s", uri);
}
af->file = tmpfile();
if (!af->file)
goto out2;
af->curl = curl_easy_init();
if (!af->curl)
goto out1;
/* Setup libcurl handle */
curl_easy_setopt(af->curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(af->curl, CURLOPT_UPLOAD, 0L);
curl_easy_setopt(af->curl, CURLOPT_USERAGENT, HTTP_USER_AGENT);
curl_easy_setopt(af->curl, CURLOPT_URL, af->uri);
curl_easy_setopt(af->curl, CURLOPT_WRITEDATA, af->file);
curl_easy_setopt(af->curl, CURLOPT_READDATA, af->file);
curl_easy_setopt(af->curl, CURLOPT_DEBUGFUNCTION, advio_trace);
curl_easy_setopt(af->curl, CURLOPT_VERBOSE, 1);
/* CURLOPT_XFERINFOFUNCTION is only supported on libcurl >= 7.32.0 */
#if LIBCURL_VERSION_NUM >= 0x072000
curl_easy_setopt(af->curl, CURLOPT_XFERINFOFUNCTION, advio_xferinfo);
curl_easy_setopt(af->curl, CURLOPT_XFERINFODATA, af);
#endif /* LIBCURL_VERSION_NUM >= 0x072000 */
ret = adownload(af, 0);
if (ret)
goto out0;
af->uploaded = 0;
af->downloaded = 0;
return af;
out0: curl_easy_cleanup(af->curl);
out1: fclose(af->file);
out2: free(af->uri);
delete af;
return nullptr;
}
int afclose(AFILE *af)
{
int ret;
ret = afflush(af);
if (ret)
return ret;
curl_easy_cleanup(af->curl);
ret = fclose(af->file);
if (ret)
return ret;
free(af->uri);
delete af;
return 0;
}
int afseek(AFILE *af, long offset, int origin)
{
long new_seek, cur_seek = aftell(af);
switch (origin) {
case SEEK_SET:
new_seek = offset;
break;
case SEEK_END:
fseek(af->file, 0, SEEK_END);
new_seek = aftell(af);
fseek(af->file, cur_seek, SEEK_SET);
break;
case SEEK_CUR:
new_seek = cur_seek + offset;
break;
default:
return -1;
}
if (new_seek < af->uploaded)
af->uploaded = new_seek;
return fseek(af->file, offset, origin);
}
void arewind(AFILE *af)
{
af->uploaded = 0;
return rewind(af->file);
}
int afflush(AFILE *af)
{
bool dirty;
unsigned char hash[SHA_DIGEST_LENGTH];
/* Check if fle was modified on disk by comparing hashes */
sha1sum(af->file, hash);
dirty = memcmp(hash, af->hash, sizeof(hash));
if (dirty)
return aupload(af, 1);
return 0;
}
int aupload(AFILE *af, int resume)
{
CURLcode res;
long pos, end;
double total_bytes = 0, total_time = 0;
char buf[2][32];
pos = aftell(af);
fseek(af->file, 0, SEEK_END);
end = aftell(af);
fseek(af->file, 0, SEEK_SET);
if (resume) {
if (end == af->uploaded)
return 0;
char *size_human = advio_human_size(end - af->uploaded, buf[0], sizeof(buf[0]));
info("Resume upload of %s of %s from offset %lu", af->uri, size_human, af->uploaded);
curl_easy_setopt(af->curl, CURLOPT_RESUME_FROM, af->uploaded);
}
else {
char *size_human = advio_human_size(end, buf[0], sizeof(buf[0]));
info("Start upload of %s of %s", af->uri, size_human);
curl_easy_setopt(af->curl, CURLOPT_RESUME_FROM, 0);
}
curl_easy_setopt(af->curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(af->curl, CURLOPT_INFILESIZE, end - af->uploaded);
curl_easy_setopt(af->curl, CURLOPT_NOPROGRESS, !isatty(fileno(stderr)));
res = curl_easy_perform(af->curl);
fseek(af->file, pos, SEEK_SET); /* Restore old stream pointer */
if (res != CURLE_OK)
return -1;
sha1sum(af->file, af->hash);
curl_easy_getinfo(af->curl, CURLINFO_SIZE_UPLOAD, &total_bytes);
curl_easy_getinfo(af->curl, CURLINFO_TOTAL_TIME, &total_time);
char *total_bytes_human = advio_human_size(total_bytes, buf[0], sizeof(buf[0]));
char *total_time_human = advio_human_time(total_time, buf[1], sizeof(buf[1]));
info("Finished upload of %s in %s", total_bytes_human, total_time_human);
af->uploaded += total_bytes;
return 0;
}
int adownload(AFILE *af, int resume)
{
CURLcode res;
long code, pos;
int ret;
double total_bytes = 0, total_time = 0;
char buf[2][32];
char *total_bytes_human, *total_time_human;
pos = aftell(af);
if (resume) {
info("Resume download of %s from offset %lu", af->uri, af->downloaded);
curl_easy_setopt(af->curl, CURLOPT_RESUME_FROM, af->downloaded);
}
else {
info("Start download of %s", af->uri);
rewind(af->file);
curl_easy_setopt(af->curl, CURLOPT_RESUME_FROM, 0);
}
curl_easy_setopt(af->curl, CURLOPT_UPLOAD, 0L);
curl_easy_setopt(af->curl, CURLOPT_NOPROGRESS, !isatty(fileno(stderr)));
res = curl_easy_perform(af->curl);
switch (res) {
case CURLE_OK:
curl_easy_getinfo(af->curl, CURLINFO_SIZE_DOWNLOAD, &total_bytes);
curl_easy_getinfo(af->curl, CURLINFO_TOTAL_TIME, &total_time);
total_bytes_human = advio_human_size(total_bytes, buf[0], sizeof(buf[0]));
total_time_human = advio_human_time(total_time, buf[1], sizeof(buf[1]));
info("Finished download of %s in %s", total_bytes_human, total_time_human);
af->downloaded += total_bytes;
af->uploaded = af->downloaded;
res = curl_easy_getinfo(af->curl, CURLINFO_RESPONSE_CODE, &code);
if (res)
return -1;
switch (code) {
case 0:
case 200: goto exist;
case 404: goto notexist;
default: return -1;
}
/* The following error codes indicate that the file does not exist
* Check the fopen mode to see if we should continue with an emoty file */
case CURLE_FILE_COULDNT_READ_FILE:
case CURLE_TFTP_NOTFOUND:
case CURLE_REMOTE_FILE_NOT_FOUND:
info("File does not exist.");
goto notexist;
/* If libcurl does not know the protocol, we will try it with the stdio */
case CURLE_UNSUPPORTED_PROTOCOL:
af->file = fopen(af->uri, af->mode);
if (!af->file)
return -1;
break;
default:
error("Failed to download file: %s: %s", af->uri, curl_easy_strerror(res));
return -1;
}
notexist: /* File does not exist */
/* According to mode the file must exist! */
if (af->mode[1] != '+' || (af->mode[0] != 'w' && af->mode[0] != 'a')) {
errno = ENOENT;
return -1;
}
/* If we receive a 404, we discard the already received error page
* and start with an empty file. */
fflush(af->file);
ret = ftruncate(fileno(af->file), 0);
if (ret)
return ret;
exist: /* File exists */
if (resume)
afseek(af, pos, SEEK_SET);
else if (af->mode[0] == 'a')
afseek(af, 0, SEEK_END);
else if (af->mode[0] == 'r' || af->mode[0] == 'w')
afseek(af, 0, SEEK_SET);
sha1sum(af->file, af->hash);
return 0;
}

View file

@ -30,6 +30,7 @@
#include <villas/table.hpp>
#include <villas/exceptions.hpp>
using namespace villas;
using namespace villas::utils;
namespace villas {
@ -132,32 +133,32 @@ double Hist::getStddev() const
return sqrt(getVar());
}
void Hist::print(bool details) const
void Hist::print(Logger logger, bool details) const
{
if (total > 0) {
Hist::cnt_t missed = total - higher - lower;
info("Counted values: %ju (%ju between %f and %f)", total, missed, low, high);
info("Highest: %g", highest);
info("Lowest: %g", lowest);
info("Mu: %g", getMean());
info("1/Mu: %g", 1.0 / getMean());
info("Variance: %g", getVar());
info("Stddev: %g", getStddev());
logger->info("Counted values: {} ({} between {} and {})", total, missed, low, high);
logger->info("Highest: {:g}", highest);
logger->info("Lowest: {:g}", lowest);
logger->info("Mu: {:g}", getMean());
logger->info("1/Mu: {:g}", 1.0 / getMean());
logger->info("Variance: {:g}", getVar());
logger->info("Stddev: {:g}", getStddev());
if (details && total - higher - lower > 0) {
char *buf = dump();
info("Matlab: %s", buf);
logger->info("Matlab: {}", buf);
free(buf);
plot();
plot(logger);
}
}
else
info("Counted values: %ju", total);
logger->info("Counted values: {}", total);
}
void Hist::plot() const
void Hist::plot(Logger logger) const
{
/* Get highest bar */
Hist::cnt_t max = *std::max_element(data.begin(), data.end());
@ -168,7 +169,7 @@ void Hist::plot() const
{ 0, TableColumn::Alignment::LEFT, "Plot", "%s", "occurences" }
};
Table table = Table(cols);
Table table = Table(logger, cols);
/* Print plot */
table.header();

View file

@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <villas/log.hpp>
#include <villas/utils.hpp>
#include <villas/config.h>
#include <villas/kernel/kernel.hpp>
@ -39,6 +40,7 @@
#include <villas/kernel/kernel.hpp>
#include <villas/exceptions.hpp>
using namespace villas;
using namespace villas::utils;
Version villas::kernel::getVersion()
@ -137,7 +139,9 @@ int villas::kernel::module_set_param(const char *module, const char *param, cons
if (!f)
throw RuntimeError("Failed set parameter {} for kernel module {} to {}", module, param, value);
debug(LOG_KERNEL | 5, "Set parameter %s of kernel module %s to %s", module, param, value);
auto logger = logging.get("kernel");
logger->debug("Set parameter {} of kernel module {} to {}", module, param, value);
fprintf(f, "%s", value);
fclose(f);
@ -150,7 +154,8 @@ int villas::kernel::module_load(const char *module)
ret = module_loaded(module);
if (!ret) {
debug(LOG_KERNEL | 5, "Kernel module %s already loaded...", module);
auto logger = logging.get("kernel");
logger->debug("Kernel module {} already loaded...", module);
return 0;
}
@ -210,10 +215,11 @@ int villas::kernel::get_cmdline_param(const char *param, char *buf, size_t len)
do {
ret = sscanf(tok, "%127[^=]=%127s", key, value);
if (ret >= 1) {
auto logger = logging.get("kernel");
if (ret >= 2)
debug(30, "Found kernel param: %s=%s", key, value);
logger->debug("Found kernel param: {}={}", key, value);
else
debug(30, "Found kernel param: %s", key);
logger->debug("Found kernel param: {}", key);
if (strcmp(param, key) == 0) {
if (ret >= 2 && buf)
@ -236,8 +242,11 @@ int villas::kernel::get_nr_hugepages()
int nr, ret;
f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "r");
if (!f)
serror("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages");
if (!f) {
auto logger = logging.get("kernel");
logger->error("Failed to open {}: {}", PROCFS_PATH "/sys/vm/nr_hugepages", strerror(errno));
return -1;
}
ret = fscanf(f, "%d", &nr);
if (ret != 1)
@ -255,13 +264,15 @@ int villas::kernel::set_nr_hugepages(int nr)
f = fopen(PROCFS_PATH "/sys/vm/nr_hugepages", "w");
if (!f) {
auto logger = logging.get("kernel");
ret = access("/.dockerenv", F_OK);
if (ret != -1) {
warning("This functionality is unavailable in this mode. Please run the Docker container in the privileged mode:");
warning(" $ docker run --privilged ...");
logger->warn("This functionality is unavailable in this mode. Please run the Docker container in the privileged mode:");
logger->warn(" $ docker run --privilged ...");
}
else
warning("Failed to open %s", PROCFS_PATH "/sys/vm/nr_hugepages");
logger->warn("Failed to open {}", PROCFS_PATH "/sys/vm/nr_hugepages");
return -1;
}

View file

@ -72,7 +72,7 @@ DeviceList::DeviceList()
ret = fscanf(f, "%x", map[i].p);
if (ret != 1)
error("Failed to parse %s ID from: %s", map[i].s, path);
throw RuntimeError("Failed to parse {} ID from: {}", map[i].s, path);
fclose(f);
}
@ -80,7 +80,7 @@ DeviceList::DeviceList()
/* Get slot id */
ret = sscanf(e->d_name, "%4x:%2x:%2x.%u", &slot.domain, &slot.bus, &slot.device, &slot.function);
if (ret != 4)
error("Failed to parse PCI slot number: %s", e->d_name);
throw RuntimeError("Failed to parse PCI slot number: {}", e->d_name);
emplace_back(std::make_shared<Device>(id, slot));
}
@ -361,7 +361,8 @@ Device::attachDriver(const std::string &driver) const
if (!f)
throw SystemError("Failed to add PCI id to {} driver ({})", driver, fn);
info("Adding ID to %s module: %04x %04x", driver.c_str(), id.vendor, id.device);
auto logger = logging.get("kernel:pci");
logger->info("Adding ID to {} module: {:04x} {:04x}", driver, id.vendor, id.device);
fprintf(f, "%04x %04x", id.vendor, id.device);
fclose(f);
@ -371,7 +372,7 @@ Device::attachDriver(const std::string &driver) const
if (!f)
throw SystemError("Failed to bind PCI device to {} driver ({})", driver, fn);
info("Bind device to %s driver", driver.c_str());
logger->info("Bind device to {} driver", driver);
fprintf(f, "%04x:%02x:%02x.%x\n", slot.domain, slot.bus, slot.device, slot.function);
fclose(f);

View file

@ -23,7 +23,6 @@
#include <list>
#include <algorithm>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/syslog_sink.h>
#include <spdlog/sinks/basic_file_sink.h>
@ -81,7 +80,7 @@ Logger Log::get(const std::string &name)
return logger;
}
void Log::parse(json_t *cfg)
void Log::parse(json_t *json)
{
const char *level = nullptr;
const char *path = nullptr;
@ -92,7 +91,7 @@ void Log::parse(json_t *cfg)
json_error_t err;
json_t *json_expressions = nullptr;
ret = json_unpack_ex(cfg, &err, JSON_STRICT, "{ s?: s, s?: s, s?: o, s?: b, s?: s }",
ret = json_unpack_ex(json, &err, JSON_STRICT, "{ s?: s, s?: s, s?: o, s?: b, s?: s }",
"level", &level,
"file", &path,
"expressions", &json_expressions,
@ -100,7 +99,7 @@ void Log::parse(json_t *cfg)
"pattern", &pattern
);
if (ret)
throw ConfigError(cfg, err, "node-config-logging");
throw ConfigError(json, err, "node-config-logging");
if (level)
setLevel(level);

View file

@ -1,153 +0,0 @@
/** Logging and debugging routines
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLAScommon
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <unistd.h>
#include <cstdio>
#include <cerrno>
#include <villas/utils.hpp>
#include <villas/log.hpp>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
using namespace villas;
using namespace villas::utils;
int log_get_width()
{
return logging.getWidth();
}
void debug(long long, const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->debug(buf);
free(buf);
}
void info(const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->info(buf);
free(buf);
}
void warning(const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->warn(buf);
free(buf);
}
void error(const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->error(buf);
free(buf);
killme(SIGABRT);
pause();
}
void serror(const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->error(buf);
free(buf);
killme(SIGABRT);
pause();
}
void jerror(json_error_t *err, const char *fmt, ...)
{
va_list ap;
char *buf;
va_start(ap, fmt);
vasprintf(&buf, fmt, ap);
va_end(ap);
Logger logger = logging.get("default");
logger->error("{}:", buf);
logger->error(" {} in {}:{}:{}", err->text, err->source, err->line, err->column);
free(buf);
killme(SIGABRT);
pause();
}
#pragma GCC diagnostic pop

View file

@ -44,11 +44,11 @@ Plugin::~Plugin()
#if 0
int
Plugin::parse(json_t *cfg)
Plugin::parse(json_t *json)
{
const char *path;
path = json_string_value(cfg);
path = json_string_value(json);
if (!path)
return -1;

View file

@ -27,8 +27,9 @@
#include <villas/table.hpp>
#include <villas/colors.hpp>
#include <villas/boxes.hpp>
#include <villas/log.h>
#include <villas/log.hpp>
using namespace villas;
using namespace villas::utils;
int Table::resize(int w)
@ -66,8 +67,8 @@ int Table::resize(int w)
void Table::header()
{
if (width != log_get_width())
resize(log_get_width());
if (width != logging.getWidth())
resize(logging.getWidth());
char *line1 = nullptr;
char *line2 = nullptr;
@ -105,9 +106,9 @@ void Table::header()
free(col);
}
info("%s", line1);
info("%s", line2);
info("%s", line3);
logger->info("{}", line1);
logger->info("{}", line2);
logger->info("{}", line3);
free(line1);
free(line2);
@ -116,8 +117,8 @@ void Table::header()
void Table::row(int count, ...)
{
if (width != log_get_width()) {
resize(log_get_width());
if (width != logging.getWidth()) {
resize(logging.getWidth());
header();
}
@ -146,6 +147,6 @@ void Table::row(int count, ...)
va_end(args);
info("%s", line);
logger->info("{}", line);
free(line);
}

View file

@ -21,7 +21,6 @@
##############################################################################
add_executable(unit-tests-common
advio.cpp
buffer.cpp
graph.cpp
hist.cpp

View file

@ -1,261 +0,0 @@
/** Unit tests for advio
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLAScommon
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <unistd.h>
#include <criterion/criterion.h>
#include <villas/utils.hpp>
#include <villas/advio.hpp>
using namespace villas;
/** This URI points to a Sciebo share which contains some test files.
* The Sciebo share is read/write accessible via WebDAV. */
#define BASE_URI "https://Q9ZHPBD5eRlZcAi:badpass@rwth-aachen.sciebo.de/public.php/webdav/tests"
// cppcheck-suppress unknownMacro
TestSuite(advio,
.description = "Advanced file IO"
);
Test(advio, islocal)
{
int ret;
ret = aislocal("/var/log/villas/dta.dat");
cr_assert_eq(ret, 1);
ret = aislocal("http://www.google.de");
cr_assert_eq(ret, 0);
ret = aislocal("torrent://www.google.de");
cr_assert_eq(ret, -1);
}
Test(advio, local)
{
AFILE *af;
int ret;
char *buf = nullptr;
size_t buflen = 0;
/* We open this file and check the first line */
af = afopen(__FILE__, "r");
cr_assert(af, "Failed to open local file");
ret = getline(&buf, &buflen, af->file);
cr_assert_gt(ret, 1);
cr_assert_str_eq(buf, "/** Unit tests for advio\n");
}
Test(advio, download)
{
AFILE *af;
int ret;
size_t len;
char buffer[65];
char expect[65] = "ook4iekohC2Teegoghu6ayoo1OThooregheebaet8Zod1angah0che7quai4ID7A";
af = afopen(BASE_URI "/download" , "r");
cr_assert(af, "Failed to download file");
len = afread(buffer, 1, sizeof(buffer), af);
cr_assert_gt(len, 0, "len=%zu, feof=%u", len, afeof(af));
cr_assert_arr_eq(buffer, expect, 64);
ret = afclose(af);
cr_assert_eq(ret, 0, "Failed to close file");
}
Test(advio, download_large)
{
AFILE *af;
int ret;
af = afopen(BASE_URI "/download-large" , "r");
cr_assert(af, "Failed to download file");
char line[4096];
char *f;
f = afgets(line, 4096, af);
cr_assert_not_null(f);
/* Check first line */
cr_assert_str_eq(line, "# VILLASnode signal params: type=mixed, values=4, rate=1000.000000, limit=100000, amplitude=1.000000, freq=1.000000\n");
while(afgets(line, 4096, af));
/* Check last line */
cr_assert_str_eq(line, "1497710478.862332239(99999) 0.752074 -0.006283 1.000000 0.996000\n");
ret = afclose(af);
cr_assert_eq(ret, 0, "Failed to close file");
}
Test(advio, resume)
{
int ret;
char *retp;
AFILE *af1, *af2;
char *fn, dir[] = "/tmp/temp.XXXXXX";
char line1[32];
char *line2 = nullptr;
size_t linelen = 0;
retp = mkdtemp(dir);
cr_assert_not_null(retp);
ret = asprintf(&fn, "%s/file", dir);
cr_assert_gt(ret, 0);
af1 = afopen(fn, "w+");
cr_assert_not_null(af1);
/* We flush once the empty file in order to upload an empty file. */
aupload(af1, 0);
af2 = afopen(fn, "r");
cr_assert_not_null(af2);
for (int i = 0; i < 100; i++) {
snprintf(line1, sizeof(line1), "This is line %d\n", i);
afputs(line1, af1);
aupload(af1, 1);
adownload(af2, 1);
ret = agetline(&line2, &linelen, af2);
cr_assert_gt(ret, 0);
cr_assert_str_eq(line1, line2);
}
ret = afclose(af1);
cr_assert_eq(ret, 0);
ret = afclose(af2);
cr_assert_eq(ret, 0);
ret = unlink(fn);
cr_assert_eq(ret, 0);
ret = rmdir(dir);
cr_assert_eq(ret, 0);
free(line2);
}
Test(advio, upload)
{
AFILE *af;
int ret;
size_t len;
char upload[64];
char buffer[64];
/* Get some random data to upload */
len = utils::read_random(upload, sizeof(upload));
cr_assert_eq(len, sizeof(upload));
/* Open file for writing */
af = afopen(BASE_URI "/upload", "w+");
cr_assert(af, "Failed to download file");
len = afwrite(upload, 1, sizeof(upload), af);
cr_assert_eq(len, sizeof(upload));
ret = afclose(af);
cr_assert_eq(ret, 0, "Failed to close/upload file");
/* Open for reading and comparison */
af = afopen(BASE_URI "/upload", "r");
cr_assert(af, "Failed to download file");
len = afread(buffer, 1, sizeof(upload), af);
cr_assert_eq(len, sizeof(upload));
cr_assert_arr_eq(buffer, upload, len);
ret = afclose(af);
cr_assert(ret == 0, "Failed to close file");
}
Test(advio, append)
{
AFILE *af;
int ret;
size_t len;
char append1[65] = "xa5gieTohlei9iu1uVaePae6Iboh3eeheeme5iejue5sheshae4uzisha9Faesei";
char append2[65] = "bitheeRae7igee2miepahJaefoGad1Ooxeif0Mooch4eojoumueYahn4ohc9poo2";
char expect[129] = "xa5gieTohlei9iu1uVaePae6Iboh3eeheeme5iejue5sheshae4uzisha9FaeseibitheeRae7igee2miepahJaefoGad1Ooxeif0Mooch4eojoumueYahn4ohc9poo2";
char buffer[129];
/* Open file for writing first chunk */
af = afopen(BASE_URI "/append", "w+");
cr_assert(af, "Failed to download file");
/* The append file might already exist and be not empty from a previous run. */
ret = ftruncate(afileno(af), 0);
cr_assert_eq(ret, 0);
char c;
fseek(af->file, 0, SEEK_SET);
if (af->file) {
while ((c = getc(af->file)) != EOF)
putchar(c);
}
len = afwrite(append1, 1, 64, af);
cr_assert_eq(len, 64);
ret = afclose(af);
cr_assert_eq(ret, 0, "Failed to close/upload file");
/* Open file for writing second chunk */
af = afopen(BASE_URI "/append", "a");
cr_assert(af, "Failed to download file");
len = afwrite(append2, 1, 64, af);
cr_assert_eq(len, 64);
ret = afclose(af);
cr_assert_eq(ret, 0, "Failed to close/upload file");
/* Open for reading and comparison */
af = afopen(BASE_URI "/append", "r");
cr_assert(af, "Failed to download file");
len = afread(buffer, 1, sizeof(buffer), af);
cr_assert_eq(len, 128);
ret = afclose(af);
cr_assert(ret == 0, "Failed to close file");
cr_assert_arr_eq(buffer, expect, 128);
}