]> pilppa.org Git - lib1wire.git/blob - src/W1Store.cc
add min,max,mean,sum and delta calculations for stored data.
[lib1wire.git] / src / W1Store.cc
1 /*
2  * W1Store.cc
3  *
4  *  Created on: Oct 31, 2010
5  *      Author: lamikr
6  */
7
8 #include <list>
9 #include <string>
10 #include <fstream>
11 #include <valarray>
12 #include <limits>
13
14 #include <time.h>
15 #include <dirent.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19
20 #include <plp/log.h>
21
22 #include "W1Configure.hh"
23 #include "W1Store.hh"
24 #include "W1Util.hh"
25
26 using namespace std;
27 using namespace w1;
28 using namespace plp;
29
30 std::string W1Store::store_base_dir     = DEFAULT_STORAGE_BASE_DIR;
31
32 W1Store::W1Store(string device_id,
33                 Date *date_time) {
34         store_data      = NULL;
35         range_data      = NULL;
36         store_file_name = get_file_name(device_id, date_time);
37         log_debug("data file name: %s\n", store_file_name.c_str());
38 }
39
40 W1Store::W1Store(string file_name_param) {
41         store_data      = NULL;
42         range_data      = NULL;
43         store_file_name = file_name_param;
44 }
45
46 W1Store::~W1Store() {
47         if (store_data != NULL) {
48                 delete(store_data);
49                 store_data      = NULL;
50         }
51 }
52
53 void W1Store::set_base_dir_name(string store_param) {
54         int     pos;
55         int     b_count;
56
57         pos     = store_param.find_last_of("/");
58         b_count = store_param.length();
59         if (pos == (b_count - 1)) {
60                 store_base_dir  = store_param;
61         }
62         else {
63                 store_base_dir  = store_param + "/";
64         }
65 }
66
67 string W1Store::get_base_dir_name() {
68         return store_base_dir;
69 }
70
71 string W1Store::get_dir_name(string device_id, Date *date_time) {
72         string  ret_val;
73         char    buffer[30];
74
75         snprintf(buffer, 30, "%d/%02d", date_time->year, date_time->month);
76         ret_val = W1Util::concat_paths(store_base_dir, device_id);
77         ret_val = ret_val + "/" + buffer;
78         return ret_val;
79 }
80
81 string W1Store::get_file_name(string device_id, Date *date_time) {
82         string  ret_val;
83         string  fname;
84         char    buffer[30];
85
86         snprintf(buffer, 30, "%d-%02d-%02d", date_time->year, date_time->month, date_time->day);
87         fname   = buffer;
88         fname   = fname + DATAFILE_SUFFIX;
89         ret_val = get_dir_name(device_id, date_time);
90         ret_val = W1Util::concat_paths(ret_val, fname);
91         return ret_val;
92 }
93
94 void W1Store::store(std::string device_id,
95                 std::list<std::string> *string_list) {
96         string          f_path;
97         string          line;
98         ofstream        *ostream;
99         Date            *date;
100
101         date    = new Date();
102         f_path  = get_file_name(device_id, date);
103         ostream = W1Util::open_for_writing(f_path.c_str());
104         // TODO: add mutex to protect string_list while it's read and emptied
105         if (ostream != NULL) {
106                 if (ostream->is_open()) {
107                         log_info("[%s] writing %d data values to file: %s\n", device_id.c_str(), string_list->size(), f_path.c_str());
108                         while(string_list->size() > 0) {
109                                 line    = string_list->front();
110                                 string_list->pop_front();
111                                 if (line.length() > 0) {
112                                         log_debug("storing line: %s\n", line.c_str());
113                                         *ostream << line << endl;
114                                 }
115                         }
116                         ostream->close();
117                 }
118                 else {
119                         log_error("[%s] Could not store data to file: %s\n", device_id.c_str(), f_path.c_str());
120                 }
121                 delete(ostream);
122         }
123         else {
124                 log_error("[%s] Could not store data to file: %s\n", device_id.c_str(), f_path.c_str());
125         }
126         delete(date);
127 }
128
129 void W1Store::load() {
130         Data            *data;
131         ifstream        in;
132         string          line;
133
134         if (store_data != NULL) {
135                 delete(store_data);
136                 store_data      = NULL;
137         }
138         in.open(store_file_name.c_str());
139         if (in.is_open() == true) {
140                 while (in.eof() == false) {
141                         getline(in, line);
142                         data    = Data::parse_data_string(line);
143                         if (store_data == NULL) {
144                                 store_data      = new DataRange(*data);
145                         }
146                         else {
147                                 store_data->add_data(*data);
148                         }
149                         delete(data);
150                 }
151         }
152 }
153
154 Data *W1Store::get_sum() {
155         int     row_count;
156         int     col_count;
157         double  new_val;
158         int     ii;
159         int     jj;
160         Date    *date;
161         Data    *data;
162         Data    *ret_val;
163
164         ret_val = NULL;
165         data    = NULL;
166         if (store_data == NULL) {
167                 load();
168         }
169         if (store_data != NULL) {
170                 row_count       = store_data->get_data_row_count();
171                 log_debug("data row count: %d\n", row_count);
172                 if (row_count > 0) {
173                         col_count       = store_data->get_data_column_count();
174                         log_debug("data item count per row: %d\n", col_count);
175                         ret_val         = new Data(col_count);
176                         if (col_count > 0) {
177                                 for (ii = 0; ii < row_count - 1; ii++) {
178                                         data    = store_data->get_data(ii);
179                                         for (jj = 0; jj < col_count; jj++) {
180                                                 new_val                 = data->value_arr[jj];
181                                                 ret_val->value_arr[jj]  = ret_val->value_arr[jj] + new_val;
182                                         }
183                                         if (ii < (row_count - 2)) {
184                                                 delete(data);
185                                                 data    = NULL;
186                                         }
187                                         //log_debug("new val: %f, sum: %f\n", new_val, sum);
188                                 }
189                         }
190                         ret_val->set_date(data->get_date());
191                         if (data != NULL) {
192                                 delete(data);
193                         }
194                 }
195         }
196         return ret_val;
197 }
198
199 Data *W1Store::get_delta() {
200         int             row_count;
201         int             col_count;
202         Data            *o_data;
203         Data            *n_data;
204         Data            *ret_val;
205         int             ii;
206         DataRange       *dr;
207
208         ret_val = NULL;
209         dr      = get_oldest_and_newest_data();
210         if (dr != NULL) {
211                 row_count       = dr->get_data_row_count();
212                 if (row_count == 2) {
213                         o_data          = dr->get_data(0);
214                         n_data          = dr->get_data(1);
215                         col_count       = dr->get_data_column_count();
216                         ret_val         = new Data(col_count);
217                         if (col_count > 0) {
218                                 for (ii = 0; ii < col_count; ii++) {
219                                         ret_val->value_arr[ii]  = n_data->value_arr[ii] - o_data->value_arr[ii];
220                                 }
221                         }
222                         ret_val->set_date(n_data->get_date());
223                         delete(o_data);
224                         delete(n_data);
225                 }
226                 delete(dr);
227         }
228         return ret_val;
229 }
230
231 Data *W1Store::get_mean() {
232         int     row_count;
233         int     col_count;
234         int     ii;
235         Data    *ret_val;
236
237         ret_val = NULL;
238         if (store_data == NULL) {
239                 load();
240         }
241         if (store_data != NULL) {
242                 row_count       = store_data->get_data_row_count();
243                 if (row_count > 0) {
244                         col_count       = store_data->get_data_column_count();
245                         ret_val         = get_sum();
246                         if (col_count > 0) {
247                                 for (ii = 0; ii < col_count; ii++) {
248                                         ret_val->value_arr[ii]  = ret_val->value_arr[ii] / row_count;
249                                         log_debug("avg: %f\n", ret_val->value_arr[ii]);
250                                 }
251                         }
252                 }
253         }
254         return ret_val;
255 }
256
257 Data *W1Store::get_max() {
258         int     row_count;
259         int     col_count;
260         double  new_val;
261         int     ii;
262         int     jj;
263         Date    *date;
264         Data    *data;
265         Data    *ret_val;
266         double  min_val;
267
268         ret_val = NULL;
269         data    = NULL;
270         if (store_data == NULL) {
271                 load();
272         }
273         if (store_data != NULL) {
274                 row_count       = store_data->get_data_row_count();
275                 log_debug("data row count: %d\n", row_count);
276                 if (row_count > 0) {
277                         col_count       = store_data->get_data_column_count();
278                         log_debug("data item count per row: %d\n", col_count);
279                         min_val         = numeric_limits<double>::min();
280                         ret_val         = new Data(col_count, min_val);
281                         if (col_count > 0) {
282                                 for (ii = 0; ii < row_count - 1; ii++) {
283                                         data    = store_data->get_data(ii);
284                                         for (jj = 0; jj < col_count; jj++) {
285                                                 new_val = data->value_arr[jj];
286                                                 if (new_val > ret_val->value_arr[jj]) {
287                                                         ret_val->value_arr[jj]  = new_val;
288                                                 }
289                                         }
290                                         if (ii < (row_count - 2)) {
291                                                 delete(data);
292                                                 data    = NULL;
293                                         }
294                                 }
295                         }
296                         ret_val->set_date(data->get_date());
297                         if (data != NULL) {
298                                 delete(data);
299                         }
300                 }
301         }
302         return ret_val;
303 }
304
305 Data *W1Store::get_min() {
306         int     row_count;
307         int     col_count;
308         double  new_val;
309         int     ii;
310         int     jj;
311         Date    *date;
312         Data    *data;
313         Data    *ret_val;
314         double  max_val;
315
316         ret_val = NULL;
317         data    = NULL;
318         if (store_data == NULL) {
319                 load();
320         }
321         if (store_data != NULL) {
322                 row_count       = store_data->get_data_row_count();
323                 log_debug("data row count: %d\n", row_count);
324                 if (row_count > 0) {
325                         col_count       = store_data->get_data_column_count();
326                         log_debug("data item count per row: %d\n", col_count);
327                         max_val         = numeric_limits<double>::max();
328                         ret_val         = new Data(col_count, max_val);
329                         if (col_count > 0) {
330                                 for (ii = 0; ii < row_count - 1; ii++) {
331                                         data    = store_data->get_data(ii);
332                                         for (jj = 0; jj < col_count; jj++) {
333                                                 new_val = data->value_arr[jj];
334                                                 if (new_val < ret_val->value_arr[jj]) {
335                                                         ret_val->value_arr[jj]  = new_val;
336                                                 }
337                                         }
338                                         if (ii < (row_count - 2)) {
339                                                 delete(data);
340                                                 data    = NULL;
341                                         }
342                                 }
343                         }
344                         ret_val->set_date(data->get_date());
345                         if (data != NULL) {
346                                 delete(data);
347                         }
348                 }
349         }
350         return ret_val;
351 }
352
353 DataRange *W1Store::get_oldest_and_newest_data() {
354         DataRange       *ret_val;
355         ifstream        in;
356         Data            *o_data;
357         Data            *n_data;
358         string          latest;
359         int             row_count;
360         string          line;
361         string          prev_line;
362
363         ret_val = NULL;
364         o_data  = NULL;
365         n_data  = NULL;
366         if (store_data != NULL) {
367                 row_count       = store_data->get_data_row_count();
368                 if (row_count > 0) {
369                         o_data          = store_data->get_data(0);
370                         n_data          = store_data->get_data(row_count - 1);
371                 }
372         }
373         else {
374                 if (range_data != NULL) {
375                         row_count       = range_data->get_data_row_count();
376                         if (row_count > 0) {
377                                 o_data          = range_data->get_data(0);
378                                 n_data          = range_data->get_data(row_count - 1);
379                         }
380                 }
381                 else {
382                         in.open(store_file_name.c_str());
383                         while (in.eof() == false) {
384                                 getline(in, line);
385                                 if (line.empty() == false) {
386                                         if (o_data == NULL) {
387                                                 o_data  = Data::parse_data_string(line);
388                                         }
389                                         prev_line       = line;
390                                 }
391                         }
392                         if (prev_line.empty() == false) {
393                                 n_data  = Data::parse_data_string(prev_line);
394                         }
395                 }
396         }
397         if ((o_data != NULL) &&
398             (n_data != NULL)) {
399                 ret_val = new DataRange(*o_data);
400                 ret_val->add_data(*n_data);
401                 if (range_data != NULL) {
402                         range_data      = new DataRange(*o_data);
403                         range_data->add_data(*n_data);
404                 }
405         }
406         if (o_data != NULL) {
407                 delete(o_data);
408         }
409         if (n_data != NULL) {
410                 delete(n_data);
411         }
412         return ret_val;
413 }
414
415 Data *W1Store::get_oldest_data() {
416         int             row_count;
417         int             col_count;
418         Data            *ret_val;
419         DataRange       *dr;
420
421         ret_val = NULL;
422         dr      = get_oldest_and_newest_data();
423         if (dr != NULL) {
424                 row_count       = dr->get_data_row_count();
425                 if (row_count >= 1) {
426                         ret_val = dr->get_data(0);
427                 }
428                 delete(dr);
429         }
430         return ret_val;
431 }
432
433 Data *W1Store::get_newest_data() {
434         int             row_count;
435         int             col_count;
436         Data            *ret_val;
437         DataRange       *dr;
438
439         ret_val = NULL;
440         dr      = get_oldest_and_newest_data();
441         if (dr != NULL) {
442                 row_count       = dr->get_data_row_count();
443                 if (row_count == 2) {
444                         ret_val = dr->get_data(1);
445                 }
446                 delete(dr);
447         }
448         return ret_val;
449 }