Commit 82a48ede authored by Julian Bigge's avatar Julian Bigge

Merge branch 'develop' into 'master'

Develop

See merge request !3
parents e214960e 29eea3b9
Pipeline #3490 passed with stage
in 41 seconds
......@@ -7,6 +7,9 @@
# Completion support
compile_commands.json
# Python cache
__pycache__/*
# Compiled Object files
*.slo
*.lo
......
......@@ -9,9 +9,9 @@ build:
# instead of calling g++ directly you can also use some build toolkit like make
# install the necessary build tools when needed
before_script:
- apt update && apt -y install make autoconf cmake libboost-dev libboost-program-options-dev
- apt update && apt -y install make autoconf cmake libboost-dev libboost-program-options-dev python python-dev
script:
- cmake . && make
- cmake -DWITHOUT_GNUPLOT=On -DWITHOUT_PYTHON=On . && make
artifacts:
paths:
- bin/sccuot
......
......@@ -4,9 +4,11 @@ project (sccuot)
set (sccuot_VERSION_MAJOR 0)
set (sccuot_VERSION_MINOR 0)
set (sccuot_VERSION_PATCH 2)
set (sccuot_VERSION_PATCH 3)
find_package (Boost COMPONENTS program_options REQUIRED)
find_package (PythonLibs 2.7)
find_package (Gnuplot)
execute_process (COMMAND mysql_config --libs
OUTPUT_VARIABLE MYSQL_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE)
......@@ -34,9 +36,26 @@ configure_file (
set (STATIC_LINKING FALSE CACHE BOOL "Build libsccuot also as static library
and links the sccuot binary statically")
set (WITHOUT_PYTHON FALSE CACHE BOOL "Build libsccuot without python backend")
set (WITHOUT_GNUPLOT FALSE CACHE BOOL "Build libsccuot without gnuplot
backend")
if (WITHOUT_PYTHON OR NOT PythonLibs_FOUND)
add_definitions (-DWITH_PYTHON=0)
else ()
add_definitions (-DWITH_PYTHON=1)
endif ()
if (WITHOUT_GNUPLOT OR NOT GNUPLOT_FOUND)
add_definitions (-DWITH_GNUPLOT=0)
else ()
add_definitions (-DWITH_GNUPLOT=1)
endif()
include_directories (${PROJECT_SOURCE_DIR}/include)
include_directories (${Boost_INCLUDE_DIRS})
include_directories (${PYTHON_INCLUDE_DIRS})
include (${PROJECT_SOURCE_DIR}/src/libsccuot/targets.cmake)
include (${PROJECT_SOURCE_DIR}/src/sccuot/targets.cmake)
......@@ -45,6 +64,12 @@ add_library ( sccuot SHARED
${LIBSCCUOT_SOURCES}
)
target_link_libraries ( sccuot
${MYSQL_LIBS}
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
)
add_executable ( sccuot_client
${SCCUOT_MAIN_SOURCES}
)
......@@ -54,6 +79,7 @@ set_target_properties (sccuot_client PROPERTIES OUTPUT_NAME sccuot)
target_link_libraries (sccuot_client
${MYSQL_LIBS}
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
)
if (STATIC_LINKING)
......
......@@ -9,7 +9,7 @@ namespace sccuot {
}
struct Csv_formatter {
void operator()(std::ostream& output, const db::Result& result);
void operator()(std::ostream& output, const db::Result& result) const;
};
} /* namespace sccuot */
#pragma once
#include <iostream>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/row.hpp>
#include <libsccuot/vis/graph.hpp>
#include <libsccuot/vis/histogram_estimation.hpp>
namespace sccuot {
template <typename ProcessorType>
class Dat_formatter {
public:
using processor_type = ProcessorType;
template <typename... Ts>
Dat_formatter(Ts&&... args)
: _processor {std::forward<Ts>(args)...}
{
}
void operator()(std::ostream& output, const db::Result& result) const
{
auto processed_result = _processor.process(result);
for (const auto& value_element : processed_result) {
output << std::get<1>(value_element) << " " << std::get<0>(value_element)
<< std::endl;
}
}
private:
mutable processor_type _processor;
};
} /* namespace sccuot */
......@@ -15,12 +15,12 @@ namespace sccuot {
virtual ~Query();
virtual const std::string& query() const override;
virtual const Result& result() const override;
virtual std::shared_ptr<Result> result() override;
private:
virtual void set_result(std::unique_ptr<Result> result) override;
std::string _query;
std::unique_ptr<Result> _result;
std::shared_ptr<Result> _result;
};
} /* namespace impl */
......
......@@ -6,7 +6,7 @@ namespace sccuot {
template <typename... Ts>
std::unique_ptr<Query> make_query(Ts&&... args)
{
return new ::sccuot::db::impl::Query {std::forward<Ts>(args)...};
return {new ::sccuot::db::impl::Query {std::forward<Ts>(args)...}};
}
} /* namespace db */
......
......@@ -11,7 +11,7 @@ namespace sccuot {
public:
friend class Connection;
virtual const std::string& query() const = 0;
virtual const Result& result() const = 0;
virtual std::shared_ptr<Result> result() = 0;
private:
virtual void set_result(std::unique_ptr<Result> result) = 0;
};
......
......@@ -35,6 +35,8 @@ namespace sccuot {
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
reverse_iterator rbegin();
......
#pragma once
#include <ratio>
namespace sccuot {
namespace detail {
class Unit_base {
public:
virtual operator double() const = 0;
virtual double get() const = 0;
};
template <typename Ratio>
class Unit : public Unit_base {
public:
explicit constexpr Unit(double value)
: _value {value / Ratio::num}
{
}
virtual operator double() const override
{
return _value;
}
virtual double get() const override
{
return _value;
}
static std::string to_string()
{
if (Ratio::num == 1) {
return "B";
} else if (Ratio::num == 1000) {
return "Kb";
} else if (Ratio::num == 1000000) {
return "Mb";
} else if (Ratio::num == 1000000000) {
return "Gb";
} else if (Ratio::num == 1000000000000) {
return "Tb";
} else {
return "";
}
}
private:
double _value;
};
} /* namespace detail */
} /* namespace sccuot */
......@@ -9,8 +9,11 @@ namespace sccuot {
class File_target : public detail::Target {
public:
using formatter_type = Formatter;
File_target(const std::string& path)
template <typename... Ts>
File_target(const std::string& path, Ts&&... args)
: _file {path, std::ios_base::out}
, _formatter {std::forward<Ts>(args)...}
{
}
......@@ -20,8 +23,8 @@ namespace sccuot {
}
private:
formatter_type _formatter;
std::ofstream _file;
formatter_type _formatter;
};
} /* namespace sccuot */
......@@ -19,8 +19,24 @@
#include <libsccuot/detail/target.hpp>
#include <libsccuot/vis/graph.hpp>
#include <libsccuot/vis/make_graph.hpp>
#include <libsccuot/vis/impl/graph.hpp>
#include <libsccuot/vis/result_processor.hpp>
#include <libsccuot/vis/histogram_estimation.hpp>
#if WITH_PYTHON == 1
#include <libsccuot/vis/python_plotter.hpp>
#endif
#if WITH_GNUPLOT == 1
#include <libsccuot/vis/gnuplot_plotter.hpp>
#endif
#include <libsccuot/csv_formatter.hpp>
#include <libsccuot/sorted_csv_formatter.hpp>
#include <libsccuot/rsorted_csv_formatter.hpp>
#include <libsccuot/sorted_csv_formatter.hpp>
#include <libsccuot/svg_formatter.hpp>
#include <libsccuot/dat_formatter.hpp>
#include <libsccuot/file_target.hpp>
#include <libsccuot/terminal_target.hpp>
......@@ -9,7 +9,7 @@ namespace sccuot {
}
struct Rsorted_csv_formatter {
void operator()(std::ostream& output, const db::Result& result);
void operator()(std::ostream& output, const db::Result& result) const;
};
} /* namespace sccuot */
......@@ -9,7 +9,7 @@ namespace sccuot {
}
struct Sorted_csv_formatter {
void operator()(std::ostream& output, const db::Result& result);
void operator()(std::ostream& output, const db::Result& result) const;
};
} /* namespace sccuot */
#pragma once
#include <iostream>
#include <libsccuot/units.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/row.hpp>
#include <libsccuot/vis/graph.hpp>
#include <libsccuot/vis/make_graph.hpp>
#if WITH_PYTHON == 1
#include <libsccuot/vis/python_plotter.hpp>
#endif
namespace sccuot {
/*
* The SVG-formatter is significantly more complex compared to the CSV-*-formatters.
*
* For plotting + preprocessing of the raw data from the SQL query we just need additional
* parameters. Logic for finding an appropriate data respresentation is outsourced into the
* `ProcessorType`. We will however need to add this variadic template for initialisation of
* this member. This especially makes not all formatters default-constructible which also
* requires the targets to accept variadic templates in its ctors to proper initialise the
* formatters.
*/
template <typename ProcessorType, typename PlotterType, typename UnitType = ::sccuot::Gb>
class Svg_formatter {
public:
using processor_type = ProcessorType;
using plotter_type = PlotterType;
template <typename... Ts>
Svg_formatter(const std::string& graph_name, Ts&&... args)
: _graph_name {graph_name}
, _processor {std::forward<Ts>(args)...}
{
}
void operator()(std::ostream& output, const db::Result& result) const
{
auto graph = vis::make_graph<PlotterType>(output);
/* Before we can plot the result data, it has to be prepared */
auto processed_result = _processor.process(result);
convert<UnitType>(processed_result);
(*graph) += {_graph_name, processed_result};
graph->set_x_label(UnitType::to_string());
graph->draw();
}
private:
std::string _graph_name;
mutable processor_type _processor;
};
} /* namespace sccuot */
......@@ -8,7 +8,10 @@ namespace sccuot {
class Terminal_target : public detail::Target {
public:
using formatter_type = Formatter;
Terminal_target(const std::string& path)
template <typename... Ts>
Terminal_target(Ts&&... args)
: _formatter {std::forward<Ts>(args)...}
{
}
......
#pragma once
#include <libsccuot/vis/graph.hpp>
#include <libsccuot/detail/units.hpp>
namespace sccuot {
using B = detail::Unit<std::ratio<1,1>>;
using Kb = detail::Unit<std::kilo>;
using Mb = detail::Unit<std::mega>;
using Gb = detail::Unit<std::giga>;
using Tb = detail::Unit<std::tera>;
constexpr B operator"" _B(long double value)
{
return B {static_cast<double>(value)};
}
constexpr Kb operator"" _Kb(long double value)
{
return Kb {static_cast<double>(value)};
}
constexpr Mb operator"" _Mb(long double value)
{
return Mb {static_cast<double>(value)};
}
constexpr Gb operator"" _Gb(long double value)
{
return Gb {static_cast<double>(value)};
}
constexpr Tb operator"" _Tb(long double value)
{
return Tb {static_cast<double>(value)};
}
template <typename UnitType>
void convert(::sccuot::vis::Graph::data_value& s)
{
for (auto& t : s) {
t = std::tuple<double, double, double> {
std::get<0>(t),
UnitType {std::get<1>(t)},
UnitType {std::get<2>(t)}
};
}
}
} /* namespace sccuot */
......@@ -2,4 +2,4 @@
#define SCCUOT_VERSION_MAJOR 0
#define SCCUOT_VERSION_MINOR 0
#define SCCUOT_VERSION_PATCH 2
#define SCCUOT_VERSION_PATCH 3
#pragma once
#include <cstdlib>
#include <fstream>
#include <libsccuot/vis/graph.hpp>
namespace sccuot {
namespace vis {
/*
* Gnuplot does not provide a native C/C++-Interface. Instead we
* will use a dedicated Gnuplot pipe to send commands to in an oldfashioned
* C-way.
*
* This especially means that this only works on POSIX compliant operating
* systems.
*
* Another "problem" is, that Gnuplot can only write SVG directly to a file.
* However sccuot has to be able to also print to terminal to be provide a
* unified interface. Because of this, we will allocate a temporary file that
* will have the same storage duration than the Gnuplot_plotter.
*/
class Gnuplot_plotter {
public:
using value = Graph::value;
using value_set = Graph::value_set;
static constexpr const char tmp_file[] = "/tmp/sccuot_gnuplot_tmp.svg";
Gnuplot_plotter();
~Gnuplot_plotter();
void operator()(std::string &output, const value_set& data);
void set_x_label(const std::string& label);
private:
FILE* _gnuplot_pipe;
std::fstream _tmp_file;
};
} /* namespace vis */
} /* namespace sccuot */
#pragma once
#include <unordered_map>
#include <vector>
#include <tuple>
#include <iosfwd>
namespace sccuot {
namespace vis {
class Graph {
public:
using data_value = std::vector<std::tuple<double, double, double>>;
using value = std::pair<std::string, std::vector<std::tuple<double, double, double>>>;
using value_set = std::unordered_map<std::string, std::vector<std::tuple<double, double, double>>>;
virtual void operator+=(const value& v) = 0;
virtual void operator+=(const value_set& s) = 0;
virtual void operator+=(value&& v) = 0;
virtual void operator+=(value_set&& s) = 0;
virtual void set_x_label(const std::string& label) = 0;
virtual void draw() = 0;
};
} /* namespace vis */
} /* namespace sccuot */
#pragma once
#include <libsccuot/db/row.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/vis/result_processor.hpp>
namespace sccuot {
namespace db {
class Result;
}
namespace vis {
class Histogram_estimation : public Result_processor {
public:
static constexpr std::size_t default_bar_width = 1;
using Result_processor::data_value;
explicit Histogram_estimation(std::size_t bin_size);
Histogram_estimation(std::size_t bin_size, std::size_t bar_width);
virtual ~Histogram_estimation() = default;
virtual data_value process(const db::Result& result) override;
private:
std::size_t _bin_size;
std::size_t _bar_width {default_bar_width};
};
} /* namespace vis */
} /* namespace sccuot */
#pragma once
#include <iosfwd>
namespace sccuot {
namespace vis {
namespace impl {
template<typename PlotterType>
class Graph : public ::sccuot::vis::Graph {
public:
using plotter_type = PlotterType;
using ::sccuot::vis::Graph::data_value;
using ::sccuot::vis::Graph::value;
using ::sccuot::vis::Graph::value_set;
Graph(std::ostream& output, value_set data = {})
: _output(output), _data {data}
{
}
virtual ~Graph() = default;
virtual void operator+=(const value& v) override
{
_data.insert(v);
}
virtual void operator+=(const value_set& s) override
{
for (const auto& entry : s) {
_data.insert(entry);
}
}
virtual void operator+=(value&& v) override
{
_data.insert(std::move(v));
}
virtual void operator+=(value_set&& s) override
{
for (auto&& entry : s) {
_data.insert(std::move(entry));
}
}
virtual void set_x_label(const std::string& label) override
{
_plotter.set_x_label(label);
}
virtual void draw() override
{
std::string plot;
_plotter(plot, _data);
_output << plot;
}
private:
plotter_type _plotter;
std::ostream& _output;
value_set _data;
};
} /* namespace impl */
} /* namespace vis */
} /* namespace sccuot */
#pragma once
namespace sccuot {
namespace vis {
class Graph;
template <typename PlotterType, typename... Ts>
std::unique_ptr<Graph> make_graph(Ts&&... args);
} /* namespace vis */
} /* namespace sccuot */
#include <libsccuot/vis/make_graph.tpp>
#include <libsccuot/vis/impl/graph.hpp>
namespace sccuot {
namespace vis {
template <typename PlotterType, typename... Ts>
std::unique_ptr<Graph> make_graph(Ts&&... args)
{
return std::unique_ptr<Graph>{new ::sccuot::vis::impl::Graph<PlotterType> {std::forward<Ts>(args)...}};
}
} /* namespace sccuot */
} /* namespace sccuot */