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

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

275 lines
6.5 KiB
C++
Raw Permalink Normal View History

/* Compare two data files.
*
2022-03-15 09:18:01 -04:00
* Author: Steffen Vogel <post@steffenvogel.de>
2022-03-15 09:28:57 -04:00
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
2022-07-04 18:20:03 +02:00
* SPDX-License-Identifier: Apache-2.0
*/
2018-07-03 21:04:28 +02:00
#include <iostream>
2021-05-10 00:12:30 +02:00
#include <unistd.h>
#include <jansson.h>
#include <villas/exceptions.hpp>
2021-05-10 00:12:30 +02:00
#include <villas/format.hpp>
2018-10-20 14:20:51 +02:00
#include <villas/log.hpp>
#include <villas/node/config.hpp>
#include <villas/pool.hpp>
#include <villas/sample.hpp>
#include <villas/tool.hpp>
#include <villas/utils.hpp>
2018-10-20 14:20:51 +02:00
using namespace villas;
namespace villas {
namespace node {
namespace tools {
2021-05-10 00:12:30 +02:00
class CompareSide {
2018-10-20 14:20:51 +02:00
public:
std::string path;
std::string dtypes;
std::string format;
struct Sample *sample;
Format *formatter;
2021-05-10 00:12:30 +02:00
FILE *stream;
2021-05-10 00:12:30 +02:00
CompareSide(const CompareSide &) = delete;
CompareSide &operator=(const CompareSide &) = delete;
2018-10-20 14:20:51 +02:00
CompareSide(const std::string &pth, const std::string &fmt,
const std::string &dt, struct Pool *p)
: path(pth), dtypes(dt), format(fmt) {
json_t *json_format;
json_error_t err;
2018-10-20 14:20:51 +02:00
// Try parsing format config as JSON
json_format = json_loads(format.c_str(), 0, &err);
formatter = json_format ? FormatFactory::make(json_format)
: FormatFactory::make(format);
if (!formatter)
throw RuntimeError("Failed to initialize formatter");
2018-10-20 14:20:51 +02:00
formatter->start(dtypes);
2021-05-10 00:12:30 +02:00
stream = fopen(path.c_str(), "r");
if (!stream)
throw SystemError("Failed to open file: {}", path);
2018-10-20 14:20:51 +02:00
sample = sample_alloc(p);
if (!sample)
throw RuntimeError("Failed to allocate samples");
}
2018-10-20 14:20:51 +02:00
~CompareSide() noexcept(false) {
int ret __attribute((unused));
2018-10-20 14:20:51 +02:00
ret = fclose(stream);
2021-05-10 00:12:30 +02:00
delete formatter;
2018-10-20 14:20:51 +02:00
sample_decref(sample);
}
};
2021-05-10 00:12:30 +02:00
class Compare : public Tool {
public:
Compare(int argc, char *argv[])
: Tool(argc, argv, "test-cmp"), pool(), epsilon(1e-6),
format("villas.human"), dtypes("64f"),
flags((int)SampleFlags::HAS_SEQUENCE | (int)SampleFlags::HAS_DATA |
(int)SampleFlags::HAS_TS_ORIGIN) {
int ret;
ret = memory::init(DEFAULT_NR_HUGEPAGES);
if (ret)
throw RuntimeError("Failed to initialize memory");
}
2019-04-17 18:46:18 +02:00
protected:
struct Pool pool;
double epsilon;
std::string format;
std::string dtypes;
int flags;
std::vector<std::string> filenames;
void usage() {
std::cout << "Usage: villas-compare [OPTIONS] FILE1 FILE2 ... FILEn"
<< std::endl
<< " FILE a list of files to compare" << std::endl
<< " OPTIONS is one or more of the following options:"
<< std::endl
<< " -d LVL adjust the debug level" << std::endl
<< " -e EPS set epsilon for floating point comparisons to EPS"
<< std::endl
<< " -v ignore data values" << std::endl
<< " -T ignore timestamp" << std::endl
<< " -s ignore sequence no" << std::endl
<< " -f FMT file format for all files" << std::endl
<< " -t DT the data-type format string" << std::endl
<< " -h show this usage information" << std::endl
<< " -V show the version of the tool" << std::endl
<< std::endl
<< "Return codes:" << std::endl
<< " 0 files are equal" << std::endl
<< " 1 file length not equal" << std::endl
<< " 2 sequence no not equal" << std::endl
<< " 3 timestamp not equal" << std::endl
<< " 4 number of values is not equal" << std::endl
<< " 5 data is not equal" << std::endl
<< std::endl;
printCopyright();
}
void parse() {
// Parse Arguments
int c;
char *endptr;
while ((c = getopt(argc, argv, "he:vTsf:t:Vd:")) != -1) {
switch (c) {
case 'e':
epsilon = strtod(optarg, &endptr);
goto check;
case 'v':
flags &= ~(int)SampleFlags::HAS_DATA;
break;
case 'T':
flags &= ~(int)SampleFlags::HAS_TS_ORIGIN;
break;
case 's':
flags &= ~(int)SampleFlags::HAS_SEQUENCE;
break;
case 'f':
format = optarg;
break;
case 't':
dtypes = optarg;
break;
case 'V':
printVersion();
exit(EXIT_SUCCESS);
case 'd':
Log::getInstance().setLevel(optarg);
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
continue;
check:
if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c,
optarg);
}
if (argc - optind < 2) {
usage();
exit(EXIT_FAILURE);
}
// Open files
for (int i = 0; i < argc - optind; i++)
filenames.push_back(argv[optind + i]);
}
int main() {
int ret, rc = 0, failed;
unsigned eofs;
ret = pool_init(&pool, filenames.size(),
SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory::heap);
if (ret)
throw RuntimeError("Failed to initialize pool");
// Open files
std::vector<CompareSide *> sides;
for (auto filename : filenames) {
auto *s = new CompareSide(filename, format, dtypes, &pool);
if (!s)
throw MemoryAllocationError();
sides.push_back(s);
}
while (true) {
// Read next sample from all files
retry:
eofs = 0;
for (auto side : sides) {
ret = feof(side->stream);
if (ret)
eofs++;
}
if (eofs) {
if (eofs == sides.size())
ret = 0;
else {
std::cout << "length unequal" << std::endl;
rc = 1;
}
goto out;
}
failed = 0;
for (auto side : sides) {
ret = side->formatter->scan(side->stream, side->sample);
if (ret <= 0)
failed++;
}
if (failed)
goto retry;
// We compare all files against the first one
for (auto side : sides) {
ret = sample_cmp(sides[0]->sample, side->sample, epsilon, flags);
if (ret) {
rc = ret;
goto out;
}
}
}
out:
for (auto side : sides)
delete side;
ret = pool_destroy(&pool);
if (ret)
throw RuntimeError("Failed to destroy pool");
return rc;
}
};
} // namespace tools
} // namespace node
} // namespace villas
int main(int argc, char *argv[]) {
villas::node::tools::Compare t(argc, argv);
return t.run();
2017-07-24 19:33:35 +02:00
}