Commit 323e869b authored by Julian Bigge's avatar Julian Bigge

Merge branch 'develop' into 'master'

New release 0.2.0

See merge request !7
parents b6d7c95a 712cb22f
Pipeline #7970 passed with stage
in 35 seconds
......@@ -19,6 +19,13 @@ __pycache__/*
# Build folder
build/
# version headers (generated by CMake)
version.hpp
# IDEA
.idea/*
cmake-build-*
# Binary output folder
bin/
......
......@@ -2,8 +2,12 @@ cmake_minimum_required (VERSION 2.7)
project (sccuot)
set (sccuot_LIB_VERSION_MAJOR 0)
set (sccuot_LIB_VERSION_MINOR 2)
set (sccuot_LIB_VERSION_PATCH 0)
set (sccuot_VERSION_MAJOR 0)
set (sccuot_VERSION_MINOR 1)
set (sccuot_VERSION_MINOR 2)
set (sccuot_VERSION_PATCH 0)
find_package (Boost COMPONENTS program_options REQUIRED)
......@@ -31,6 +35,11 @@ configure_file (
"${PROJECT_SOURCE_DIR}/include/libsccuot/version.hpp"
)
configure_file (
"${PROJECT_SOURCE_DIR}/src/sccuot/version.hpp.in"
"${PROJECT_SOURCE_DIR}/src/sccuot/version.hpp"
)
set (STATIC_LIB FALSE CACHE BOOL "Build libsccuot also as static library
and links the sccuot binary statically")
......
......@@ -2,8 +2,6 @@
#include <iostream>
#include <libsccuot/representor.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/row.hpp>
namespace sccuot {
......
......@@ -6,6 +6,7 @@ namespace sccuot {
namespace db {
class Result;
class Extquery;
}
class Dataframe {
......@@ -18,6 +19,7 @@ namespace sccuot {
Dataframe() = default;
explicit Dataframe(const db::Result& result);
explicit Dataframe(const db::Extquery& equery);
const data_type& data() const;
data_type& data();
......@@ -39,10 +41,15 @@ namespace sccuot {
std::vector<float>& operator[](std::size_t pos);
const std::vector<float>& operator[](std::size_t pos) const;
void add_row(const std::vector<float>& row);
void add_row(std::vector<float>&& row);
void sort_x();
void sort_y();
void sort();
Dataframe relative(std::size_t frow, std::size_t srow) const;
iterator begin();
iterator end();
const_iterator begin() const;
......
......@@ -2,6 +2,7 @@
#include <mysql/mysql.h>
#include <libsccuot/db/query.hpp>
#include <libsccuot/db/ext_query.hpp>
namespace sccuot {
namespace db {
......@@ -12,6 +13,8 @@ namespace sccuot {
~Connection();
Connection& operator<<(Query& query);
Connection& operator<<(Extquery& equery);
private:
MYSQL _connection;
......
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "query.hpp"
namespace sccuot {
namespace db {
class Extquery {
public:
using arglist = std::vector<std::string>;
using query_ptr = std::unique_ptr<::sccuot::db::Query>;
using querylist = std::vector<query_ptr>;
using iterator = typename querylist::iterator;
using const_iterator = typename querylist::const_iterator;
virtual ~Extquery() = default;
virtual std::size_t num_queries() const = 0;
virtual iterator begin() = 0;
virtual iterator end() = 0;
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual const_iterator cbegin() const = 0;
virtual const_iterator cend() const = 0;
};
Extquery::arglist args(const std::string& args);
}
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ namespace sccuot {
class Consumed_space_query : public Query {
public:
Consumed_space_query()
: Query {"select sum(size) from oc_filecache where path='files';"}
: Query("select sum(size) from oc_filecache where path='files';")
{
}
};
......
#pragma once
#include "../ext_query.hpp"
#include "query.hpp"
namespace sccuot {
namespace db {
namespace impl {
class Extquery : public virtual ::sccuot::db::Extquery {
public:
using ::sccuot::db::Extquery::arglist;
using ::sccuot::db::Extquery::query_ptr;
using ::sccuot::db::Extquery::querylist;
using ::sccuot::db::Extquery::iterator;
using ::sccuot::db::Extquery::const_iterator;
Extquery() = default;
explicit Extquery(const arglist& args, querylist&& queries = {});
explicit Extquery(arglist&& args, querylist&& queries = {});
Extquery(const Extquery&) = delete;
Extquery& operator=(const Extquery&) = delete;
~Extquery() override = default;
std::size_t num_queries() const override;
iterator begin() override;
iterator end() override;
const_iterator begin() const override;
const_iterator end() const override;
const_iterator cbegin() const override;
const_iterator cend() const override;
protected:
arglist _args;
querylist _queries;
};
} /* namespace impl */
} /* namespace db */
} /* namespace sccuot */
\ No newline at end of file
......@@ -9,7 +9,7 @@ namespace sccuot {
class Ext_shares_count_query : public Query {
public:
Ext_shares_count_query()
: Query {"select count(*) from oc_share_external;"}
: Query("select count(*) from oc_share_external;")
{
}
};
......
#pragma once
#include <memory>
#include <libsccuot/db/impl/ext_query.hpp>
namespace sccuot {
namespace db {
namespace impl {
class File_type_count_query : public Extquery {
public:
using Extquery::arglist;
using Extquery::querylist;
explicit File_type_count_query(arglist&& args)
: Extquery(std::move(args))
{
for (const auto& arg : _args) {
_queries.emplace_back(
new sccuot::db::impl::Query(std::string {"select count(*) from oc_filecache where name like '%" + arg + "';"}));
}
}
};
} /* namespace impl */
} /* namespace db */
} /* namespace sccuot */
......@@ -9,7 +9,7 @@ namespace sccuot {
class Files_count_query : public Query {
public:
Files_count_query()
: Query {"select count(*) from oc_filecache;"}
: Query("select count(*) from oc_filecache;")
{
}
};
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class Links_count_query : public Query {
public:
Links_count_query()
: Query {"select count(*) from oc_share where share_with is NULL;"}
: Query("select count(*) from oc_share where share_with is NULL;")
{
}
};
......
......@@ -9,18 +9,23 @@ namespace sccuot {
namespace impl {
class Query : public ::sccuot::db::Query {
class Query : public virtual ::sccuot::db::Query {
public:
explicit Query(const std::string& query);
virtual ~Query();
Query(const sccuot::db::impl::Query&) = delete;
sccuot::db::impl::Query& operator=(const sccuot::db::impl::Query&) = delete;
~Query() override = default;
virtual const std::string& query() const override;
virtual std::shared_ptr<Result> result() override;
private:
virtual void set_result(std::unique_ptr<Result> result) override;
const std::string& query() const override;
std::shared_ptr<Result> result() override;
protected:
virtual void finalise_result();
std::string _query;
std::shared_ptr<Result> _result;
void set_result(std::unique_ptr<Result> result) override;
};
} /* namespace impl */
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class Shared_dirs_count_query : public Query {
public:
Shared_dirs_count_query()
: Query {"select count(*) from oc_share where item_type = 'folder';"}
: Query("select count(*) from oc_share where item_type = 'folder';")
{
}
};
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class Shared_files_count_query : public Query {
public:
Shared_files_count_query()
: Query {"select count(*) from oc_share where item_type = 'file';"}
: Query("select count(*) from oc_share where item_type = 'file';")
{
}
};
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class Shares_count_query : public Query {
public:
Shares_count_query()
: Query {"select count(*) from oc_share;"}
: Query("select count(*) from oc_share;")
{
}
};
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class User_consumed_space_query : public Query {
public:
User_consumed_space_query()
: Query {"select size from oc_filecache where path='files';"}
: Query("select size from oc_filecache where path='files';")
{
}
};
......
......@@ -9,7 +9,7 @@ namespace sccuot {
class User_count_query : public Query {
public:
User_count_query()
: Query {"select count(*) from oc_filecache where path='files';"}
: Query("select count(*) from oc_filecache where path='files';")
{
}
};
......
#pragma once
#include <libsccuot/db/impl/query.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace sccuot {
namespace db {
namespace impl {
class User_quota_query : public Query {
public:
User_quota_query()
: Query(
"select fc.size, a.quota from oc_mounts m, oc_filecache fc, oc_storages s, oc_accounts"
" a where m.mount_point=concat('/', m.user_id, '/') and s.numeric_id=m.storage_id and fc.storage="
"m.storage_id and fc.path='files' and m.user_id = a.user_id;"
)
{
}
};
} /* namespace impl */
} /* namespace db */
} /* namespace sccuot */
#pragma once
#include <map>
#include "ext_query.hpp"
namespace sccuot {
namespace db {
namespace impl {
class Users_query : public Extquery {
public:
using Extquery::arglist;
using Extquery::querylist;
explicit Users_query(arglist&& args)
: Extquery(std::move(args))
{
for (const auto& arg : _args) {
_queries.emplace_back(
new ::sccuot::db::impl::Query(std::string {
"select count(*) from oc_accounts where DATE_SUB(CURDATE(), INTERVAL "
+ std::to_string(opts.at(arg)) + " DAY) <= from_unixtime(last_login);"
})
);
}
}
private:
const std::map<std::string, std::size_t> opts = {
{"daily", 1},
{"weekly", 7},
{"monthly", 30},
{"quarter", 90}
};
};
} /* namespace impl */
} /* namespace db */
} /* namespace sccuot */
\ No newline at end of file
......@@ -10,9 +10,11 @@ namespace sccuot {
class Query {
public:
friend class Connection;
virtual ~Query() = default;
virtual const std::string& query() const = 0;
virtual std::shared_ptr<Result> result() = 0;
private:
protected:
virtual void set_result(std::unique_ptr<Result> result) = 0;
};
......
......@@ -2,7 +2,10 @@
#include <boost/lexical_cast.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/units.hpp>
#include <libsccuot/formats.hpp>
#include <mysql/mysql.h>
#include <boost/algorithm/string/predicate.hpp>
namespace sccuot {
namespace db {
......@@ -15,7 +18,28 @@ namespace sccuot {
template <typename ResultType>
ResultType as(std::size_t idx) const
{
return boost::lexical_cast<ResultType>(_row[idx]);
/* For our SQL-Queries we have some special values that we have to take care of */
if (_row[idx] == nullptr) {
return ResultType{0};
}
std::string s {_row[idx]};
if (boost::iequals(s, "none") || boost::iequals(s, "default") || boost::iequals(s, "unlimited")) {
return ResultType{0};
}
/* We also have fields with a unit. We always convert them to bytes */
if (s.find_last_of(' ') != std::string::npos) {
std::string field_unit {s.substr(s.find_last_of(' ') + 1)};
s = {s.substr(0, s.find_last_of(' '))};
unit u = string_to_unit(field_unit);
return boost::lexical_cast<ResultType>(convert_from_to(std::stof(s), u, unit::b));
}
return boost::lexical_cast<ResultType>(s);
}
std::size_t num_fields() const
......
......@@ -12,7 +12,8 @@ namespace sccuot {
using data_value = std::vector<std::size_t>;
using const_iterator = data_value::const_iterator;
Histogram(const Dataframe& df, std::size_t bin_size);
Histogram(const Dataframe& df, std::size_t bin_count);
Histogram(const Dataframe& df, std::size_t bin_count, float min, float max);
std::size_t size() const;
std::size_t bin_size() const;
......
......@@ -3,19 +3,24 @@
#include <libsccuot/version.hpp>
#include <libsccuot/db/connection.hpp>
#include <libsccuot/db/query.hpp>
#include <libsccuot/db/ext_query.hpp>
#include <libsccuot/db/make_query.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/row.hpp>
#include <libsccuot/db/impl/query.hpp>
#include <libsccuot/db/impl/ext_query.hpp>
#include <libsccuot/db/impl/consumed_space_query.hpp>
#include <libsccuot/db/impl/ext_shares_count_query.hpp>
#include <libsccuot/db/impl/files_count_query.hpp>
#include <libsccuot/db/impl/file_type_count_query.hpp>
#include <libsccuot/db/impl/links_count_query.hpp>
#include <libsccuot/db/impl/shared_dirs_count_query.hpp>
#include <libsccuot/db/impl/shared_files_count_query.hpp>
#include <libsccuot/db/impl/shares_count_query.hpp>
#include <libsccuot/db/impl/user_consumed_space_query.hpp>
#include <libsccuot/db/impl/user_count_query.hpp>
#include <libsccuot/db/impl/user_quota_query.hpp>
#include <libsccuot/db/impl/users_query.hpp>
#include <libsccuot/detail/units.hpp>
#include <libsccuot/dataframe.hpp>
......@@ -34,3 +39,11 @@
#include <libsccuot/dat_formatter.hpp>
#include <libsccuot/file_target.hpp>
#include <libsccuot/terminal_target.hpp>
namespace sccuot {
std::string libversion() {
return std::to_string(LIBSCCUOT_VERSION_MAJOR) + "."
+ std::to_string(LIBSCCUOT_VERSION_MINOR) + "."
+ std::to_string(LIBSCCUOT_VERSION_PATCH);
}
}
#pragma once
#define SCCUOT_VERSION_MAJOR 0
#define SCCUOT_VERSION_MINOR 1
#define SCCUOT_VERSION_PATCH 1
#pragma once
#define SCCUOT_VERSION_MAJOR @sccuot_VERSION_MAJOR@
#define SCCUOT_VERSION_MINOR @sccuot_VERSION_MINOR@
#define SCCUOT_VERSION_PATCH @sccuot_VERSION_PATCH@
#define LIBSCCUOT_VERSION_MAJOR @sccuot_LIB_VERSION_MAJOR@
#define LIBSCCUOT_VERSION_MINOR @sccuot_LIB_VERSION_MINOR@
#define LIBSCCUOT_VERSION_PATCH @sccuot_LIB_VERSION_PATCH@
......@@ -3,11 +3,14 @@
#include <numeric>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/row.hpp>
#include <libsccuot/db/ext_query.hpp>
#include <libsccuot/dataframe.hpp>
namespace sccuot {
Dataframe::Dataframe(const db::Result& result)
: _size {0}
{
_data.reserve(result.num_rows());
......@@ -24,6 +27,26 @@ namespace sccuot {
}
}
Dataframe::Dataframe(const db::Extquery& equery)
: _size {0}
{
_data.reserve(equery.num_queries());
for (const auto& p : equery) {
for (const auto& row : *(p->result())) {
std::vector<float> row_values;
row_values.reserve(row.num_fields());
for (std::size_t i = 0; i < row.num_fields(); ++i) {
++_size;
row_values.push_back(row.as<float>(i));
}
_data.push_back(std::move(row_values));
}
}
}
const typename Dataframe::data_type& Dataframe::data() const
{
return _data;
......@@ -62,7 +85,7 @@ namespace sccuot {
float Dataframe::max() const
{
float ret;
float ret = 0;
for (const auto& v: _data) {
ret = std::max(*std::max_element(v.begin(), v.end()), ret);
......@@ -147,6 +170,18 @@ namespace sccuot {
}
}
void Dataframe::add_row(const std::vector<float>& row)
{
_data.push_back(row);
_size += row.size();
}
void Dataframe::add_row(std::vector<float>&& row)
{
_data.push_back(row);
_size += row.size();
}
void Dataframe::sort_y()
{
std::sort(_data.begin(), _data.end(), [](const std::vector<float>& l, const std::vector<float>& r)
......@@ -161,6 +196,22 @@ namespace sccuot {
this->sort_y();
}
Dataframe Dataframe::relative(std::size_t fcol, std::size_t scol) const
{
Dataframe ret;
std::vector<float> r;
std::transform(this->begin(), this->end(), std::back_inserter(r),
[fcol, scol](const std::vector<float>& s) {
return s[fcol] == 0.0f ? 0.0f : s[scol] / s[fcol] * 100.0f;
});
ret._size = r.size();
ret._data.push_back(std::move(r));
return ret;
}
typename Dataframe::iterator Dataframe::begin()
{
return _data.begin();
......
......@@ -39,5 +39,20 @@ namespace sccuot {
return *this;
}
Connection& Connection::operator<<(Extquery& equery)
{
for (auto& q : equery) {
if (mysql_query(&_connection, q->query().c_str())) {
throw std::runtime_error{std::string{"Failed to query database: "} + mysql_error(&_connection)};
}
auto result = new Result{mysql_store_result(&_connection)};
q->set_result(std::unique_ptr<Result>{result});
}
return *this;
}
} /* namespace db */
} /* namespace db */
#include <libsccuot/db/row.hpp>
#include <libsccuot/db/result.hpp>
#include <libsccuot/db/impl/query.hpp>
#include <libsccuot/db/impl/ext_query.hpp>
#include <algorithm>
namespace sccuot {
namespace db {
namespace impl {
Extquery::Extquery(const arglist& args, querylist&& queries)
: _args {args}, _queries