]> pilppa.org Git - lib1wire.git/blob - src/StoreDay.cc
8d35952f5a3321f60501172fdbdc40445f989b58
[lib1wire.git] / src / StoreDay.cc
1 /*
2  * Store.cc
3  *
4  *  Created on: Oct 31, 2010
5  *      Author: lamikr
6  */
7
8 #include <list>
9 #include <string>
10 #include <fstream>
11 #include <limits>
12
13 #include <time.h>
14 #include <dirent.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18
19 #include <plp/log.h>
20
21 #include "DeviceConfig.hh"
22 #include "W1Configure.hh"
23 #include "StoreDay.hh"
24 #include "W1Util.hh"
25
26 using namespace std;
27 using namespace w1;
28 using namespace plp;
29
30 StoreDay::StoreDay(string device_id_param,
31                 Date *date_time_param): Store(device_id_param, date_time_param) {
32         store_fname     = get_file_name(device_id_param, date_time_param);
33 }
34
35 StoreDay::StoreDay(string fname_param): Store("", NULL) {
36         store_data      = NULL;
37         range_data      = NULL;
38         store_fname     = fname_param;
39 }
40
41 StoreDay::~StoreDay() {
42         if (store_data != NULL) {
43                 delete(store_data);
44                 store_data      = NULL;
45         }
46 }
47
48 string StoreDay::get_dir_name(string device_id, Date *date_time_param) {
49         string  ret_val;
50         char    buffer[30];
51         string  bd_name;
52
53         snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
54         bd_name = DeviceConfig::get_base_dir_name();
55         bd_name = W1Util::concat_paths(bd_name, device_id);
56         ret_val = bd_name + "/" + buffer;
57         return ret_val;
58 }
59
60 string StoreDay::get_file_name(string device_id, Date *date_time_param) {
61         string  ret_val;
62         string  fname;
63         char    buffer[30];
64
65         snprintf(buffer, 30, "%d-%02d-%02d", date_time_param->year, date_time_param->month, date_time_param->day);
66         fname   = buffer;
67         fname   = fname + DATAFILE_SUFFIX;
68         ret_val = get_dir_name(device_id, date_time_param);
69         ret_val = W1Util::concat_paths(ret_val, fname);
70         return ret_val;
71 }
72
73 void StoreDay::save(string device_id,
74                 std::list<Data *> *data_list,
75                 int dec_precision) {
76         string                  n_path;
77         string                  f_path;
78         string                  line;
79         Data                    *data;
80         ofstream                *ostream;
81         Date                    date;
82         list<Data *>::iterator  iter;
83
84         ostream =  NULL;
85         f_path  = "";
86         log_info("[%s] writing %d data values to save.\n", device_id.c_str(), data_list->size());
87         // TODO: add mutex to protect string_list while it's read and emptied
88         for(iter = data_list->begin(); iter != data_list->end(); iter++) {
89                 data    = (Data *)*iter;
90                 date    = data->get_date();
91                 n_path  = get_file_name(device_id, &date);
92                 if (n_path.compare(f_path) != 0) {
93                         if (ostream != NULL) {
94                                 ostream->close();
95                                 delete(ostream);
96                         }
97                         f_path  = n_path;
98                         log_info("[%s] Opening file for save: %s\n", device_id.c_str(), f_path.c_str());
99                         ostream = W1Util::open_for_writing(f_path.c_str());
100                 }
101                 if ((ostream != NULL) &&
102                     (ostream->is_open() == true)) {
103                         line    = data->to_string(dec_precision);
104                         if (line.length() > 0) {
105                                 log_debug("storing line: %s\n", line.c_str());
106                                 *ostream << line << endl;
107                         }
108                 }
109                 else {
110                         log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), f_path.c_str());
111                 }
112         }
113         if (ostream != NULL) {
114                 ostream->close();
115                 delete(ostream);
116         }
117 }
118
119 bool StoreDay::load() {
120         return Store::load(store_fname);
121 }
122
123 bool StoreDay::exist(string fname_param) {
124         bool    ret_val;
125         ret_val = (access(fname_param.c_str(), F_OK) == 0);
126         return ret_val;
127 }
128
129 bool StoreDay::exist() {
130         return exist(store_fname);
131 }
132
133 static int get_summary_period_as_freq_seconds(EnumSummaryPeriod period_type_param) {
134         int     ret_val;
135
136         ret_val = 3600;
137         switch(period_type_param) {
138                 case PERIOD_SECONDLY:
139                         ret_val = 1;
140                         break;
141                 case PERIOD_MINUTELY:
142                         ret_val = 60;
143                         break;
144                 case PERIOD_HOURLY:
145                         ret_val = 3600;
146                         break;
147                 case PERIOD_DAILY:
148                 case PERIOD_MONTHLY:
149                 case PERIOD_YEARLY:
150                 default:
151                         // -1 as freq means that show all data from the current store
152                         ret_val = -1;
153                         break;
154         }
155         return ret_val;
156 }
157
158 plp::DataRange *StoreDay::get_sum(EnumSummaryPeriod period_type_param) {
159         int             row_count;
160         int             col_count;
161         int             jj;
162         int             ii;
163         Data            *data;
164         Data            *calc;
165         Date            *limit_d;
166         Date            date;
167         DataRange       *ret_val;
168         int             frq_sec;
169
170         ret_val = new DataRange();
171         calc    = NULL;
172         limit_d = NULL;
173         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
174         if (store_data == NULL) {
175                 load();
176         }
177         if (store_data != NULL) {
178                 row_count       = store_data->get_count();
179                 if (row_count > 0) {
180                         col_count       = store_data->get_data_item_value_count();
181                         if (col_count > 0) {
182                                 for (ii = 0; ii < row_count; ii++) {
183                                         data    = store_data->get(ii);
184                                         if (data != NULL) {
185                                                 if (calc == NULL) {
186                                                         calc            = data->clone();
187                                                         limit_d         = data->get_date().clone();
188                                                         limit_d->min    = 0;
189                                                         limit_d->sec    = 0;
190                                                         limit_d->inc_seconds(frq_sec);
191                                                 }
192                                                 else {
193                                                         date    = data->get_date();
194                                                         if ((ii <= (row_count -1)) &&
195                                                             ((frq_sec == -1) || (date.before(limit_d)))) {
196                                                                 for (jj = 0; jj < col_count; jj++) {
197                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
198                                                                 }
199                                                         }
200                                                         if ((ii >= (row_count -1)) ||
201                                                             ((frq_sec != -1) && (date.before(limit_d) == false))) {
202                                                                 ret_val->add(calc);
203                                                                 delete(calc);
204                                                                 calc    = data->clone();
205                                                                 if (limit_d != NULL) {
206                                                                         delete(limit_d);
207                                                                 }
208                                                                 limit_d         = data->get_date().clone();
209                                                                 limit_d->min    = 0;
210                                                                 limit_d->sec    = 0;
211                                                                 limit_d->inc_seconds(frq_sec);
212                                                         }
213                                                 }
214                                                 delete(data);
215                                         }
216                                 }
217                                 if (calc != NULL) {
218                                         delete(calc);
219                                         calc    = NULL;
220                                 }
221                                 if (limit_d != NULL) {
222                                         delete(limit_d);
223                                 }
224                         }
225                 }
226         }
227         return ret_val;
228 }
229
230 plp::DataRange *StoreDay::get_mean(EnumSummaryPeriod period_type_param) {
231         int             row_count;
232         int             col_count;
233         int             d_count;
234         int             jj;
235         int             ii;
236         Data            *data;
237         Data            *calc;
238         Date            *limit_d;
239         Date            date;
240         DataRange       *ret_val;
241         int             frq_sec;
242
243         ret_val = new DataRange();
244         calc    = NULL;
245         limit_d = NULL;
246         d_count = 1;
247         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
248         if (store_data == NULL) {
249                 load();
250         }
251         if (store_data != NULL) {
252                 row_count       = store_data->get_count();
253                 if (row_count > 0) {
254                         col_count       = store_data->get_data_item_value_count();
255                         if (col_count > 0) {
256                                 for (ii = 0; ii < row_count; ii++) {
257                                         data    = store_data->get(ii);
258                                         if (data != NULL) {
259                                                 if (calc == NULL) {
260                                                         d_count         = 1;
261                                                         calc            = data->clone();
262                                                         limit_d         = data->get_date().clone();
263                                                         limit_d->min    = 0;
264                                                         limit_d->sec    = 0;
265                                                         limit_d->inc_seconds(frq_sec);
266                                                 }
267                                                 else {
268                                                         date    = data->get_date();
269                                                         if ((ii <= (row_count -1)) &&
270                                                             ((frq_sec == -1) || (date.before(limit_d)))) {
271                                                                 for (jj = 0; jj < col_count; jj++) {
272                                                                         calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
273                                                                 }
274                                                                 d_count++;
275                                                         }
276                                                         if ((ii >= (row_count -1)) ||
277                                                             ((frq_sec != -1) && (date.before(limit_d) == false))) {
278                                                                 for (jj = 0; jj < col_count; jj++) {
279                                                                         calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
280                                                                 }
281                                                                 ret_val->add(calc);
282                                                                 delete(calc);
283                                                                 d_count         = 1;
284                                                                 calc            = data->clone();
285                                                                 if (limit_d != NULL) {
286                                                                         delete(limit_d);
287                                                                 }
288                                                                 limit_d         = data->get_date().clone();
289                                                                 limit_d->min    = 0;
290                                                                 limit_d->sec    = 0;
291                                                                 limit_d->inc_seconds(frq_sec);
292                                                         }
293                                                 }
294                                                 delete(data);
295                                         }
296                                 }
297                                 if (calc != NULL) {
298                                         delete(calc);
299                                         calc    = NULL;
300                                 }
301                                 if (limit_d != NULL) {
302                                         delete(limit_d);
303                                 }
304                         }
305                 }
306         }
307         return ret_val;
308 }
309
310 plp::DataRange *StoreDay::get_delta(EnumSummaryPeriod period_type_param) {
311         int             row_count;
312         int             col_count;
313         int             jj;
314         int             ii;
315         Data            *data;
316         Data            *calc1;
317         Data            *calc2;
318         Date            *limit_d;
319         Date            date;
320         DataRange       *ret_val;
321         int             frq_sec;
322
323         ret_val = new DataRange();
324         calc1   = NULL;
325         calc2   = NULL;
326         limit_d = NULL;
327         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
328         if (store_data == NULL) {
329                 load();
330         }
331         if (store_data != NULL) {
332                 row_count       = store_data->get_count();
333                 if (row_count > 0) {
334                         col_count       = store_data->get_data_item_value_count();
335                         if (col_count > 0) {
336                                 for (ii = 0; ii < row_count; ii++) {
337                                         data    = store_data->get(ii);
338                                         if (data != NULL) {
339                                                 if (calc1 == NULL) {
340                                                         calc1           = data->clone();
341                                                         limit_d         = data->get_date().clone();
342                                                         limit_d->min    = 0;
343                                                         limit_d->sec    = 0;
344                                                         limit_d->inc_seconds(frq_sec);
345                                                         if (calc2 != NULL) {
346                                                                 delete(calc2);
347                                                         }
348                                                         calc2           = NULL;
349                                                 }
350                                                 else {
351                                                         date    = data->get_date();
352                                                         if ((ii <= (row_count -1)) &&
353                                                             ((frq_sec == -1) || (date.before(limit_d)))) {
354                                                                 if (calc2 != NULL) {
355                                                                         delete(calc2);
356                                                                 }
357                                                                 calc2   = data->clone();
358                                                         }
359                                                         if ((ii >= (row_count -1)) ||
360                                                             ((frq_sec != -1) && (date.before(limit_d) == false))) {
361                                                                 if (calc2 == NULL) {
362                                                                         calc2   = calc1->clone();
363                                                                 }
364                                                                 for (jj = 0; jj < col_count; jj++) {
365                                                                         calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
366                                                                 }
367                                                                 ret_val->add(calc2);
368                                                                 delete(calc1);
369                                                                 calc1   = data->clone();
370                                                                 delete(calc2);
371                                                                 calc2   = NULL;
372                                                                 if (limit_d != NULL) {
373                                                                         delete(limit_d);
374                                                                 }
375                                                                 limit_d         = data->get_date().clone();
376                                                                 limit_d->min    = 0;
377                                                                 limit_d->sec    = 0;
378                                                                 limit_d->inc_seconds(frq_sec);
379                                                         }
380                                                 }
381                                                 delete(data);
382                                         }
383                                 }
384                                 if (calc1 != NULL) {
385                                         delete(calc1);
386                                         calc1   = NULL;
387                                 }
388                                 if (calc2 != NULL) {
389                                         delete(calc2);
390                                         calc2   = NULL;
391                                 }
392                                 if (limit_d != NULL) {
393                                         delete(limit_d);
394                                 }
395                         }
396                 }
397         }
398         return ret_val;
399 }
400
401 plp::DataRange *StoreDay::get_max_or_min(EnumSummaryPeriod period_type_param, bool max) {
402         int             row_count;
403         int             col_count;
404         int             jj;
405         int             ii;
406         Data            *data;
407         Data            *calc;
408         Date            *limit_d;
409         Date            date;
410         DataRange       *ret_val;
411         int             frq_sec;
412
413         ret_val = new DataRange();
414         calc    = NULL;
415         limit_d = NULL;
416         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
417         if (store_data == NULL) {
418                 load();
419         }
420         if (store_data != NULL) {
421                 row_count       = store_data->get_count();
422                 if (row_count > 0) {
423                         col_count       = store_data->get_data_item_value_count();
424                         if (col_count > 0) {
425                                 for (ii = 0; ii < row_count; ii++) {
426                                         data    = store_data->get(ii);
427                                         if (data != NULL) {
428                                                 if (calc == NULL) {
429                                                         calc            = data->clone();
430                                                         limit_d         = data->get_date().clone();
431                                                         limit_d->min    = 0;
432                                                         limit_d->sec    = 0;
433                                                         limit_d->inc_seconds(frq_sec);
434                                                 }
435                                                 else {
436                                                         date    = data->get_date();
437                                                         if ((ii <= (row_count -1)) &&
438                                                             ((frq_sec == -1) || (date.before(limit_d)))) {
439                                                                 if (max == true) {
440                                                                         for (jj = 0; jj < col_count; jj++) {
441                                                                                 if (calc->value_arr[jj] < data->value_arr[jj]) {
442                                                                                         calc->value_arr[jj]     = data->value_arr[jj];
443                                                                                 }
444                                                                         }
445                                                                 }
446                                                                 else {
447                                                                         for (jj = 0; jj < col_count; jj++) {
448                                                                                 if (data->value_arr[jj] < calc->value_arr[jj]) {
449                                                                                         calc->value_arr[jj]     = data->value_arr[jj];
450                                                                                 }
451                                                                         }
452                                                                 }
453                                                         }
454                                                         if ((ii >= (row_count -1)) ||
455                                                             ((frq_sec != -1) && (date.before(limit_d) == false))) {
456                                                                 ret_val->add(calc);
457                                                                 delete(calc);
458                                                                 calc    = data->clone();
459                                                                 if (limit_d != NULL) {
460                                                                         delete(limit_d);
461                                                                 }
462                                                                 limit_d         = data->get_date().clone();
463                                                                 limit_d->min    = 0;
464                                                                 limit_d->sec    = 0;
465                                                                 limit_d->inc_seconds(frq_sec);
466                                                         }
467                                                 }
468                                                 delete(data);
469                                         }
470                                 }
471                                 if (calc != NULL) {
472                                         delete(calc);
473                                         calc    = NULL;
474                                 }
475                                 if (limit_d != NULL) {
476                                         delete(limit_d);
477                                 }
478                         }
479                 }
480         }
481         return ret_val;
482 }
483
484 plp::DataRange *StoreDay::get_max(EnumSummaryPeriod period_type_param) {
485         DataRange       *ret_val;
486
487         ret_val = get_max_or_min(period_type_param, true);
488         return ret_val;
489 }
490
491 plp::DataRange *StoreDay::get_min(EnumSummaryPeriod period_type_param) {
492         DataRange       *ret_val;
493
494         ret_val = get_max_or_min(period_type_param, false);
495         return ret_val;
496 }
497
498 DataRange *StoreDay::get_oldest_and_newest_data(string fname_param) {
499         DataRange       *ret_val;
500         ifstream        in;
501         Data            *o_data;
502         Data            *n_data;
503         string          latest;
504         int             row_count;
505         string          line;
506         string          prev_line;
507
508         ret_val = NULL;
509         o_data  = NULL;
510         n_data  = NULL;
511         if (store_data != NULL) {
512                 row_count       = store_data->get_count();
513                 if (row_count > 0) {
514                         o_data          = store_data->get(0);
515                         n_data          = store_data->get(row_count - 1);
516                 }
517         }
518         else {
519                 if (range_data != NULL) {
520                         row_count       = range_data->get_count();
521                         if (row_count > 0) {
522                                 o_data          = range_data->get(0);
523                                 n_data          = range_data->get(row_count - 1);
524                         }
525                 }
526                 else {
527                         in.open(fname_param.c_str());
528                         while (in.eof() == false) {
529                                 getline(in, line);
530                                 if (line.empty() == false) {
531                                         if (o_data == NULL) {
532                                                 o_data  = Data::parse_string(line);
533                                         }
534                                         prev_line       = line;
535                                 }
536                         }
537                         if (prev_line.empty() == false) {
538                                 n_data  = Data::parse_string(prev_line);
539                         }
540                 }
541         }
542         if ((o_data != NULL) &&
543             (n_data != NULL)) {
544                 ret_val = new DataRange(o_data);
545                 ret_val->add(n_data);
546                 if (range_data != NULL) {
547                         range_data      = new DataRange(o_data);
548                         range_data->add(n_data);
549                 }
550         }
551         if (o_data != NULL) {
552                 delete(o_data);
553         }
554         if (n_data != NULL) {
555                 delete(n_data);
556         }
557         return ret_val;
558 }
559
560 DataRange *StoreDay::get_oldest_and_newest_data() {
561         return get_oldest_and_newest_data(store_fname);
562 }
563
564 Data *StoreDay::get_oldest_data() {
565         int             row_count;
566         Data            *ret_val;
567         DataRange       *dr;
568
569         ret_val = NULL;
570         dr      = get_oldest_and_newest_data();
571         if (dr != NULL) {
572                 row_count       = dr->get_count();
573                 if (row_count >= 1) {
574                         ret_val = dr->get(0);
575                 }
576                 delete(dr);
577         }
578         return ret_val;
579 }
580
581 Data *StoreDay::get_newest_data() {
582         int             row_count;
583         Data            *ret_val;
584         DataRange       *dr;
585
586         ret_val = NULL;
587         dr      = get_oldest_and_newest_data();
588         if (dr != NULL) {
589                 row_count       = dr->get_count();
590                 if (row_count == 2) {
591                         ret_val = dr->get(1);
592                 }
593                 delete(dr);
594         }
595         return ret_val;
596 }