Line data Source code
1 : /*! @brief This file have the implementation for DataAccess class.
2 : @file dataaccess.cc
3 : @author Alvaro Denis <denisacostaq@gmail.com>
4 : @date 6/22/2019
5 :
6 : @copyright
7 : @attention <h1><center><strong>COPYRIGHT © 2019 </strong>
8 : [<strong>denisacostaq</strong>][denisacostaq-URL].
9 : All rights reserved.</center></h1>
10 : @attention This file is part of [<strong>DAQs</strong>][DAQs-URL].
11 :
12 : Redistribution and use in source and binary forms, with or without
13 : modification, are permitted provided that the following conditions
14 : are met:
15 : - 1. Redistributions of source code must retain the above copyright
16 : notice, this list of conditions and the following disclaimer.
17 : - 2. Redistributions in binary form must reproduce the above copyright
18 : notice, this list of conditions and the following disclaimer in the
19 : documentation and/or other materials provided with the distribution.
20 : - 3. Neither the name of the University nor the names of its contributors
21 : may be used to endorse or promote products derived from this software
22 : without specific prior written permission.
23 :
24 : THIS PRODUCT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 : ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
28 : DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 : ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 : THIS PRODUCT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 :
35 : [denisacostaq-URL]: https://about.me/denisacostaq "Alvaro Denis Acosta"
36 : [DAQs-URL]: https://github.com/denisacostaq/DAQs "DAQs"
37 : */
38 : #include "src/database-server/data-access/dataaccess.h"
39 :
40 : #include <algorithm>
41 : #include <cmath>
42 :
43 28 : DataAccess::DataAccess(IDataSource* ds) noexcept : IDataAccess{}, ds_{ds} {}
44 :
45 10 : IDataAccess::Err DataAccess::add_variable(const Variable& var) noexcept {
46 10 : return ds_->add_variable(var) == IDataSource::Err::Ok ? Err::Ok : Err::Failed;
47 : }
48 :
49 20 : IDataAccess::Err DataAccess::add_variable_value(const VarValue& var) noexcept {
50 20 : return ds_->add_variable_value(var) == IDataSource::Err::Ok ? Err::Ok
51 20 : : Err::Failed;
52 : }
53 :
54 14 : IDataAccess::Err DataAccess::compress(const std::vector<VarValue>& in_vals,
55 : std::vector<VarValue>* out_vals,
56 : size_t max_len) noexcept {
57 : try {
58 14 : out_vals->reserve(max_len);
59 0 : } catch (const std::length_error& e) {
60 0 : std::cerr << e.what() << "\n";
61 0 : return IDataAccess::Err::InvalidArgument;
62 : }
63 : auto apply_compression{[&in_vals, &out_vals](size_t chunk_size,
64 : size_t in_vals_offset,
65 184 : size_t chunk_ammont) {
66 28 : auto begin{in_vals.begin()};
67 28 : std::advance(begin, in_vals_offset);
68 28 : auto mid{in_vals.begin()};
69 28 : std::advance(mid, in_vals_offset + chunk_size / 2);
70 28 : auto end{in_vals.begin()};
71 28 : std::advance(end, in_vals_offset + chunk_size);
72 228 : for (size_t i{0}; i < chunk_ammont; ++i, std::advance(begin, chunk_size),
73 200 : std::advance(end, chunk_size),
74 100 : std::advance(mid, chunk_size)) {
75 100 : double sum{.0};
76 100 : std::for_each(begin, end,
77 718 : [&sum](const VarValue& val) { sum += val.val(); });
78 200 : VarValue val{};
79 100 : val.set_val(sum / chunk_size);
80 100 : val.set_timestamp(mid->timestamp());
81 100 : out_vals->emplace_back(std::move(val));
82 : }
83 42 : }};
84 : auto ceil_chunk_size{static_cast<size_t>(
85 14 : std::ceil(static_cast<double>(in_vals.size()) / max_len))};
86 22 : auto ceil_ammount{(in_vals.size() % max_len) ? in_vals.size() % max_len
87 22 : : in_vals.size() / max_len};
88 14 : apply_compression(ceil_chunk_size, 0, ceil_ammount);
89 14 : auto floor_chunk_sieze{in_vals.size() / max_len};
90 14 : auto floor_ammount{max_len - ceil_ammount};
91 14 : apply_compression(floor_chunk_sieze, ceil_chunk_size * ceil_ammount,
92 : floor_ammount);
93 14 : return Err::Ok;
94 : }
95 :
96 : std::tuple<std::vector<Variable>, IDataAccess::Err>
97 4 : DataAccess::fetch_variables() noexcept {
98 8 : std::vector<Variable> variables{};
99 12 : if (ds_->fetch_variables([&variables](const Variable& var, size_t index) {
100 0 : variables.push_back(var);
101 8 : }) != IDataSource::Err::Ok) {
102 2 : return std::make_tuple(std::vector<Variable>{}, Err::Failed);
103 : }
104 2 : return std::make_tuple(variables, Err::Ok);
105 : }
106 :
107 : std::tuple<std::vector<VarValue>, IDataAccess::Err>
108 8 : DataAccess::fetch_variable_values(const std::string& var_name,
109 : size_t max_len) noexcept {
110 16 : std::vector<VarValue> tmp_values{};
111 24 : if (ds_->fetch_variable_values(
112 10 : var_name, [&tmp_values](const VarValue& val, size_t index) {
113 10 : tmp_values.push_back(val);
114 26 : }) != IDataSource::Err::Ok) {
115 2 : return std::make_tuple(std::vector<VarValue>{}, Err::Failed);
116 : }
117 6 : if (max_len != std::numeric_limits<decltype(max_len)>::infinity() &&
118 0 : tmp_values.size() > max_len) {
119 0 : std::vector<VarValue> values{};
120 0 : auto err{compress(tmp_values, &values, max_len)};
121 0 : if (err != Err::Ok) {
122 0 : return std::make_tuple(std::vector<VarValue>{}, Err::Ok);
123 : }
124 0 : std::clog << "compression from " << tmp_values.size() << " to "
125 0 : << values.size() << "\n";
126 0 : return std::make_tuple(values, Err::Ok);
127 : }
128 6 : return std::make_tuple(tmp_values, Err::Ok);
129 : }
130 :
131 : std::tuple<std::vector<VarValue>, IDataAccess::Err>
132 4 : DataAccess::fetch_variable_values(
133 : const std::string& var_name,
134 : const std::chrono::system_clock::time_point& start_date,
135 : const std::chrono::system_clock::time_point& end_date,
136 : size_t max_len) noexcept {
137 8 : std::vector<VarValue> tmp_values{};
138 12 : if (ds_->fetch_variable_values(
139 : var_name, start_date, end_date,
140 0 : [&tmp_values](const VarValue& val, size_t index) {
141 0 : tmp_values.push_back(val);
142 8 : }) != IDataSource::Err::Ok) {
143 2 : return std::make_tuple(std::vector<VarValue>{}, Err::Failed);
144 : }
145 2 : if (max_len != std::numeric_limits<decltype(max_len)>::infinity() &&
146 0 : tmp_values.size() > max_len) {
147 0 : std::vector<VarValue> values{};
148 0 : auto err{compress(tmp_values, &values, max_len)};
149 0 : if (err != Err::Ok) {
150 0 : return std::make_tuple(std::vector<VarValue>{}, Err::Ok);
151 : }
152 0 : return std::make_tuple(std::move(values), Err::Ok);
153 : }
154 2 : return std::make_tuple(std::move(tmp_values), Err::Ok);
155 84 : }
|