diff --git a/common/include/villas/advio.hpp b/common/include/villas/advio.hpp deleted file mode 100644 index 1e0dbcea4..000000000 --- a/common/include/villas/advio.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/** libcurl based advanced IO aka ADVIO. - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#pragma once - -#include - -#include - -#include -#include - -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); diff --git a/common/include/villas/hist.hpp b/common/include/villas/hist.hpp index a81498e0b..33233e422 100644 --- a/common/include/villas/hist.hpp +++ b/common/include/villas/hist.hpp @@ -27,6 +27,8 @@ #include +#include + #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. * diff --git a/common/include/villas/list.h b/common/include/villas/list.h index e20601060..e463ae479 100644 --- a/common/include/villas/list.h +++ b/common/include/villas/list.h @@ -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 - /** Lookup an element from the list based on an UUID */ template 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); \ No newline at end of file +int vlist_init_and_push(struct vlist *l, void *p); diff --git a/common/include/villas/log.h b/common/include/villas/log.h deleted file mode 100644 index 1576f4306..000000000 --- a/common/include/villas/log.h +++ /dev/null @@ -1,101 +0,0 @@ -/** Logging and debugging routines - * - * @file - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#pragma once - -#include - -#include - -/* 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))); diff --git a/common/include/villas/log.hpp b/common/include/villas/log.hpp index 322fa9ab8..891c6d253 100644 --- a/common/include/villas/log.hpp +++ b/common/include/villas/log.hpp @@ -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); diff --git a/common/include/villas/plugin.hpp b/common/include/villas/plugin.hpp index 2664ba1b3..4014aaaa1 100644 --- a/common/include/villas/plugin.hpp +++ b/common/include/villas/plugin.hpp @@ -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 { diff --git a/common/include/villas/table.hpp b/common/include/villas/table.hpp index 27729e088..c2ad2b12b 100644 --- a/common/include/villas/table.hpp +++ b/common/include/villas/table.hpp @@ -30,6 +30,10 @@ #include #include +#include + +namespace villas { + class Table; class TableColumn { @@ -78,10 +82,13 @@ protected: std::vector columns; + Logger logger; + public: - Table(const std::vector &cols) : + Table(Logger log, const std::vector &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 */ + /** @} */ diff --git a/common/include/villas/utils.hpp b/common/include/villas/utils.hpp index c25b7fac6..0e63d388f 100644 --- a/common/include/villas/utils.hpp +++ b/common/include/villas/utils.hpp @@ -40,7 +40,6 @@ #include #include -#include #ifdef __GNUC__ #define LIKELY(x) __builtin_expect((x),1) diff --git a/common/lib/CMakeLists.txt b/common/lib/CMakeLists.txt index cb0062299..0149a8e37 100644 --- a/common/lib/CMakeLists.txt +++ b/common/lib/CMakeLists.txt @@ -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) diff --git a/common/lib/advio.cpp b/common/lib/advio.cpp deleted file mode 100644 index fb2238ed8..000000000 --- a/common/lib/advio.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/** libcurl based advanced IO aka ADVIO. - * - * This example requires libcurl 7.9.7 or later. - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#if __GNUC__ <= 7 && !defined(__clang__) - #include - namespace fs = std::experimental::filesystem; -#else - #include - namespace fs = std::filesystem; -#endif - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -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; -} diff --git a/common/lib/hist.cpp b/common/lib/hist.cpp index df4f47a0e..54cefd584 100644 --- a/common/lib/hist.cpp +++ b/common/lib/hist.cpp @@ -30,6 +30,7 @@ #include #include +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(); diff --git a/common/lib/kernel/kernel.cpp b/common/lib/kernel/kernel.cpp index c0d57fc0d..775bb1a9c 100644 --- a/common/lib/kernel/kernel.cpp +++ b/common/lib/kernel/kernel.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include +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; } diff --git a/common/lib/kernel/pci.cpp b/common/lib/kernel/pci.cpp index 482d49380..b6570bc7b 100644 --- a/common/lib/kernel/pci.cpp +++ b/common/lib/kernel/pci.cpp @@ -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(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); diff --git a/common/lib/log.cpp b/common/lib/log.cpp index 2545c7f83..fa9bdb367 100644 --- a/common/lib/log.cpp +++ b/common/lib/log.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -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); diff --git a/common/lib/log_legacy.cpp b/common/lib/log_legacy.cpp deleted file mode 100644 index 6f8c5e747..000000000 --- a/common/lib/log_legacy.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/** Logging and debugging routines - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include -#include -#include - -#include -#include - -#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 diff --git a/common/lib/plugin.cpp b/common/lib/plugin.cpp index 38ea29c47..4846cecd7 100644 --- a/common/lib/plugin.cpp +++ b/common/lib/plugin.cpp @@ -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; diff --git a/common/lib/table.cpp b/common/lib/table.cpp index 3d63d9f31..5b830d7d9 100644 --- a/common/lib/table.cpp +++ b/common/lib/table.cpp @@ -27,8 +27,9 @@ #include #include #include -#include +#include +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); } diff --git a/common/tests/unit/CMakeLists.txt b/common/tests/unit/CMakeLists.txt index 27658725d..283b0810c 100644 --- a/common/tests/unit/CMakeLists.txt +++ b/common/tests/unit/CMakeLists.txt @@ -21,7 +21,6 @@ ############################################################################## add_executable(unit-tests-common - advio.cpp buffer.cpp graph.cpp hist.cpp diff --git a/common/tests/unit/advio.cpp b/common/tests/unit/advio.cpp deleted file mode 100644 index 0315b906c..000000000 --- a/common/tests/unit/advio.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/** Unit tests for advio - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include - -#include - -#include -#include - -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); -}