]> pilppa.org Git - libplp.git/blob - src/StoreDay.cc
fix possibility for unitialized variable
[libplp.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 "log.h"
20 #include "DeviceConfig.hh"
21 #include "StoreDay.hh"
22 #include "FileUtil.hh"
23
24 using namespace std;
25 using namespace plp;
26
27 StoreDay::StoreDay(string device_id_param,
28                 Date *date_time_param): Store(device_id_param, date_time_param) {
29         store_fname     = get_file_name(device_id_param, date_time_param);
30 }
31
32 StoreDay::StoreDay(string fname_param): Store("", NULL) {
33         store_data      = NULL;
34         range_data      = NULL;
35         store_fname     = fname_param;
36 }
37
38 StoreDay::~StoreDay() {
39         if (store_data != NULL) {
40                 delete(store_data);
41                 store_data      = NULL;
42         }
43 }
44
45 string StoreDay::get_year_dir_name(string device_id,
46                                 Date *date_time_param) {
47         string  ret_val;
48         char    buffer[10];
49         string  bd_name;
50
51         snprintf(buffer, 10, "%d", date_time_param->year);
52         bd_name = DeviceConfig::get_base_dir_name();
53         bd_name = FileUtil::concat_paths(bd_name, device_id);
54         ret_val = bd_name + "/" + buffer;
55         return ret_val;
56 }
57
58 string StoreDay::get_dir_name(string device_id,
59                         Date *date_time_param) {
60         string  ret_val;
61         char    buffer[30];
62         string  bd_name;
63
64         snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
65         bd_name = DeviceConfig::get_base_dir_name();
66         bd_name = FileUtil::concat_paths(bd_name, device_id);
67         ret_val = bd_name + "/" + buffer;
68         return ret_val;
69 }
70
71 string StoreDay::get_file_name(string device_id,
72                         Date *date_time_param) {
73         string  ret_val;
74         string  fname;
75         char    buffer[30];
76
77         snprintf(buffer,
78                 30,
79                 "%d-%02d-%02d",
80                 date_time_param->year,
81                 date_time_param->month,
82                 date_time_param->day);
83         fname   = buffer;
84         fname   = fname + DATAFILE_SUFFIX;
85         ret_val = get_dir_name(device_id, date_time_param);
86         ret_val = FileUtil::concat_paths(ret_val, fname);
87         return ret_val;
88 }
89
90 void StoreDay::save(string device_id,
91                 std::list<Data *> *data_list,
92                 int dec_precision) {
93         string                  n_path;
94         string                  f_path;
95         string                  line;
96         Data                    *data;
97         ofstream                *ostream;
98         Date                    date;
99         list<Data *>::iterator  iter;
100
101         ostream =  NULL;
102         f_path  = "";
103         /* needs to be casted to long unsigned int value is "unsigned int" in some
104            toolchains and that would otherwise cause an warning/error 
105         */
106         log_info("[%s] saving %lu data values.\n", device_id.c_str(),
107                 (long unsigned int)data_list->size());
108         // TODO: add mutex to protect string_list while it's read and emptied
109         for(iter = data_list->begin(); iter != data_list->end(); iter++) {
110                 data    = (Data *)*iter;
111                 date    = data->get_date();
112                 n_path  = get_file_name(device_id, &date);
113                 if (n_path.compare(f_path) != 0) {
114                         if (ostream != NULL) {
115                                 ostream->close();
116                                 delete(ostream);
117                         }
118                         f_path  = n_path;
119                         log_info("[%s] Opening file for save: %s\n", device_id.c_str(), f_path.c_str());
120                         ostream = FileUtil::open_for_writing(f_path.c_str());
121                 }
122                 if ((ostream != NULL) &&
123                     (ostream->is_open() == true)) {
124                         line    = data->to_string(dec_precision);
125                         if (line.length() > 0) {
126                                 log_debug("storing line: %s\n", line.c_str());
127                                 *ostream << line << endl;
128                         }
129                 }
130                 else {
131                         log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), f_path.c_str());
132                 }
133         }
134         if (ostream != NULL) {
135                 ostream->close();
136                 delete(ostream);
137         }
138 }
139
140 bool StoreDay::load() {
141         return Store::load(store_fname);
142 }
143
144 bool StoreDay::exist(string fname_param, bool writable) {
145         bool    ret_val;
146         ret_val = FileUtil::file_exist(fname_param.c_str(), writable);
147         return ret_val;
148 }
149
150 bool StoreDay::exist(string dev_id_param,
151                 Date *date,
152                 bool writable) {
153         bool    ret_val;
154         string  f_name;
155
156         f_name  = get_file_name(dev_id_param, date);
157         ret_val = FileUtil::file_exist(f_name.c_str(), writable);
158         return ret_val;
159 }
160
161 bool StoreDay::exist_in_month(string dev_id_param,
162                         Date *date,
163                         bool writable) {
164         string  dirname;
165         bool    ret_val;
166
167         dirname = StoreDay::get_dir_name(dev_id_param, date);
168         ret_val = FileUtil::dir_exist(dirname.c_str(), writable);
169         return ret_val;
170 }
171
172 bool StoreDay::exist_in_year(string dev_id_param,
173                         Date *date,
174                         bool writable) {
175         string  dirname;
176         bool    ret_val;
177
178         dirname = StoreDay::get_year_dir_name(dev_id_param, date);
179         ret_val = FileUtil::dir_exist(dirname.c_str(), writable);
180         return ret_val;
181 }
182
183 bool StoreDay::exist(bool writable) {
184         return exist(store_fname, writable);
185 }
186
187 static int get_summary_period_as_freq_seconds(EnumSummaryPeriod period_type_param) {
188         int     ret_val;
189
190         ret_val = 3600;
191         switch(period_type_param) {
192                 case PERIOD_SECONDLY:
193                         ret_val = 1;
194                         break;
195                 case PERIOD_MINUTELY:
196                         ret_val = 60;
197                         break;
198                 case PERIOD_HOURLY:
199                         ret_val = 3600;
200                         break;
201                 case PERIOD_DAILY:
202                 case PERIOD_MONTHLY:
203                 case PERIOD_YEARLY:
204                 default:
205                         // -1 as freq means that show all data from the current store
206                         ret_val = -1;
207                         break;
208         }
209         return ret_val;
210 }
211
212 plp::DataRange *StoreDay::get_sum(EnumSummaryPeriod period_type_param) {
213         int             row_count;
214         int             col_count;
215         int             jj;
216         int             ii;
217         Data            *data;
218         Data            *calc;
219         Date            *limit_d;
220         Date            date;
221         DataRange       *ret_val;
222         int             frq_sec;
223         bool            succ;
224
225         ret_val = NULL;
226         calc    = NULL;
227         limit_d = NULL;
228         succ    = true;
229         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
230         if (store_data == NULL) {
231                 succ    = load();
232         }
233         if ((succ == true) &&
234             (store_data != NULL)) {
235                 row_count       = store_data->get_count();
236                 if (row_count > 0) {
237                         col_count       = store_data->get_data_item_value_count();
238                         if (col_count > 0) {
239                                 ret_val = new DataRange();
240                                 for (ii = 0; ii < row_count; ii++) {
241                                         data    = store_data->get(ii);
242                                         if (data != NULL) {
243                                                 if (calc == NULL) {
244                                                         calc            = data->clone();
245                                                         limit_d         = data->get_date().clone();
246                                                         limit_d->min    = 0;
247                                                         limit_d->sec    = 0;
248                                                         limit_d->inc_seconds(frq_sec);
249                                                 }
250                                                 date    = data->get_date();
251                                                 if ((ii <= (row_count -1)) &&
252                                                     ((frq_sec == -1) || (date.before(limit_d)))) {
253                                                         for (jj = 0; jj < col_count; jj++) {
254                                                                 calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
255                                                         }
256                                                 }
257                                                 if ((ii >= (row_count -1)) ||
258                                                     ((frq_sec != -1) && (date.before(limit_d) == false))) {
259                                                         ret_val->add(calc);
260                                                         delete(calc);
261                                                         calc    = data->clone();
262                                                         if (limit_d != NULL) {
263                                                                 delete(limit_d);
264                                                         }
265                                                         limit_d         = data->get_date().clone();
266                                                         limit_d->min    = 0;
267                                                         limit_d->sec    = 0;
268                                                         limit_d->inc_seconds(frq_sec);
269                                                 }
270                                                 delete(data);
271                                         }
272                                 }
273                                 if (calc != NULL) {
274                                         delete(calc);
275                                         calc    = NULL;
276                                 }
277                                 if (limit_d != NULL) {
278                                         delete(limit_d);
279                                 }
280                         }
281                 }
282         }
283         return ret_val;
284 }
285
286 plp::DataRange *StoreDay::get_mean(EnumSummaryPeriod period_type_param) {
287         int             row_count;
288         int             col_count;
289         int             d_count;
290         int             jj;
291         int             ii;
292         Data            *data;
293         Data            *calc;
294         Date            *limit_d;
295         Date            date;
296         DataRange       *ret_val;
297         int             frq_sec;
298         bool            succ;
299
300         ret_val = NULL;
301         calc    = NULL;
302         limit_d = NULL;
303         d_count = 1;
304         succ    = true;
305         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
306         if (store_data == NULL) {
307                 succ    = load();
308         }
309         if ((succ == true) &&
310             (store_data != NULL)) {
311                 row_count       = store_data->get_count();
312                 if (row_count > 0) {
313                         col_count       = store_data->get_data_item_value_count();
314                         if (col_count > 0) {
315                                 ret_val = new DataRange();
316                                 for (ii = 0; ii < row_count; ii++) {
317                                         data    = store_data->get(ii);
318                                         if (data != NULL) {
319                                                 if (calc == NULL) {
320                                                         d_count         = 1;
321                                                         calc            = data->clone();
322                                                         limit_d         = data->get_date().clone();
323                                                         limit_d->min    = 0;
324                                                         limit_d->sec    = 0;
325                                                         limit_d->inc_seconds(frq_sec);
326                                                 }
327                                                 date    = data->get_date();
328                                                 if ((ii <= (row_count -1)) &&
329                                                     ((frq_sec == -1) || (date.before(limit_d)))) {
330                                                         for (jj = 0; jj < col_count; jj++) {
331                                                                 calc->value_arr[jj]     = calc->value_arr[jj] + data->value_arr[jj];
332                                                         }
333                                                         d_count++;
334                                                 }
335                                                 if ((ii >= (row_count -1)) ||
336                                                     ((frq_sec != -1) && (date.before(limit_d) == false))) {
337                                                         for (jj = 0; jj < col_count; jj++) {
338                                                                 calc->value_arr[jj]     = calc->value_arr[jj] / d_count;
339                                                         }
340                                                         ret_val->add(calc);
341                                                         delete(calc);
342                                                         d_count         = 1;
343                                                         calc            = data->clone();
344                                                         if (limit_d != NULL) {
345                                                                 delete(limit_d);
346                                                         }
347                                                         limit_d         = data->get_date().clone();
348                                                         limit_d->min    = 0;
349                                                         limit_d->sec    = 0;
350                                                         limit_d->inc_seconds(frq_sec);
351                                                 }
352                                                 delete(data);
353                                         }
354                                 }
355                                 if (calc != NULL) {
356                                         delete(calc);
357                                         calc    = NULL;
358                                 }
359                                 if (limit_d != NULL) {
360                                         delete(limit_d);
361                                 }
362                         }
363                 }
364         }
365         return ret_val;
366 }
367
368 plp::DataRange *StoreDay::get_delta(EnumSummaryPeriod period_type_param) {
369         int             row_count;
370         int             col_count;
371         int             jj;
372         int             ii;
373         Data            *data;
374         Data            *calc1;
375         Data            *calc2;
376         Date            *limit_d;
377         Date            date;
378         DataRange       *ret_val;
379         int             frq_sec;
380         bool            succ;
381
382         ret_val = NULL;
383         calc1   = NULL;
384         calc2   = NULL;
385         limit_d = NULL;
386         succ    = true;
387         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
388         if (store_data == NULL) {
389                 succ    = load();
390         }
391         if ((succ == true) &&
392             (store_data != NULL)) {
393                 row_count       = store_data->get_count();
394                 if (row_count > 0) {
395                         col_count       = store_data->get_data_item_value_count();
396                         if (col_count > 0) {
397                                 ret_val = new DataRange();
398                                 for (ii = 0; ii < row_count; ii++) {
399                                         data    = store_data->get(ii);
400                                         if (data != NULL) {
401                                                 if (calc1 == NULL) {
402                                                         calc1           = data->clone();
403                                                         limit_d         = data->get_date().clone();
404                                                         limit_d->min    = 0;
405                                                         limit_d->sec    = 0;
406                                                         limit_d->inc_seconds(frq_sec);
407                                                         if (calc2 != NULL) {
408                                                                 delete(calc2);
409                                                         }
410                                                         calc2           = NULL;
411                                                 }
412                                                 date    = data->get_date();
413                                                 if ((ii <= (row_count -1)) &&
414                                                     ((frq_sec == -1) || (date.before(limit_d)))) {
415                                                         if (calc2 != NULL) {
416                                                                 delete(calc2);
417                                                         }
418                                                         calc2   = data->clone();
419                                                 }
420                                                 if ((ii >= (row_count -1)) ||
421                                                     ((frq_sec != -1) && (date.before(limit_d) == false))) {
422                                                         if (calc2 == NULL) {
423                                                                 calc2   = calc1->clone();
424                                                         }
425                                                         for (jj = 0; jj < col_count; jj++) {
426                                                                 calc2->value_arr[jj]    = calc2->value_arr[jj] - calc1->value_arr[jj];
427                                                         }
428                                                         ret_val->add(calc2);
429                                                         delete(calc1);
430                                                         calc1   = data->clone();
431                                                         delete(calc2);
432                                                         calc2   = NULL;
433                                                         if (limit_d != NULL) {
434                                                                 delete(limit_d);
435                                                         }
436                                                         limit_d         = data->get_date().clone();
437                                                         limit_d->min    = 0;
438                                                         limit_d->sec    = 0;
439                                                         limit_d->inc_seconds(frq_sec);
440                                                 }
441                                                 delete(data);
442                                         }
443                                 }
444                                 if (calc1 != NULL) {
445                                         delete(calc1);
446                                         calc1   = NULL;
447                                 }
448                                 if (calc2 != NULL) {
449                                         delete(calc2);
450                                         calc2   = NULL;
451                                 }
452                                 if (limit_d != NULL) {
453                                         delete(limit_d);
454                                 }
455                         }
456                 }
457         }
458         return ret_val;
459 }
460
461 plp::DataRange *StoreDay::get_max_or_min(EnumSummaryPeriod period_type_param, bool max) {
462         int             row_count;
463         int             col_count;
464         int             jj;
465         int             ii;
466         Data            *data;
467         Data            *calc;
468         Date            *limit_d;
469         Date            date;
470         DataRange       *ret_val;
471         int             frq_sec;
472         bool            succ;
473
474         ret_val = NULL;
475         calc    = NULL;
476         limit_d = NULL;
477         frq_sec = get_summary_period_as_freq_seconds(period_type_param);
478         succ    = true;
479         if (store_data == NULL) {
480                 succ    = load();
481         }
482         if ((succ == true) &&
483             (store_data != NULL)) {
484                 row_count       = store_data->get_count();
485                 if (row_count > 0) {
486                         col_count       = store_data->get_data_item_value_count();
487                         if (col_count > 0) {
488                                 ret_val = new DataRange();
489                                 for (ii = 0; ii < row_count; ii++) {
490                                         data    = store_data->get(ii);
491                                         if (data != NULL) {
492                                                 if (calc == NULL) {
493                                                         calc            = data->clone();
494                                                         limit_d         = data->get_date().clone();
495                                                         limit_d->min    = 0;
496                                                         limit_d->sec    = 0;
497                                                         limit_d->inc_seconds(frq_sec);
498                                                 }
499                                                 date    = data->get_date();
500                                                 if ((ii <= (row_count -1)) &&
501                                                     ((frq_sec == -1) || (date.before(limit_d)))) {
502                                                         int changed = 0;
503                                                         if (max == true) {
504                                                                 for (jj = 0; jj < col_count; jj++) {
505                                                                         if (calc->value_arr[jj] < data->value_arr[jj]) {
506                                                                                 calc->value_arr[jj]     = data->value_arr[jj];
507                                                                                 changed = 1;
508                                                                         }
509                                                                 }
510                                                         }
511                                                         else {
512                                                                 for (jj = 0; jj < col_count; jj++) {
513                                                                         if (data->value_arr[jj] < calc->value_arr[jj]) {
514                                                                                 calc->value_arr[jj]     = data->value_arr[jj];
515                                                                                 changed = 1;
516                                                                         }
517                                                                 }
518                                                         }
519                                                         if (changed == 1) {
520                                                                 Date new_date;
521
522                                                                 new_date        = data->get_date();
523                                                                 calc->set_date(&new_date);
524                                                         }
525                                                 }
526                                                 if ((ii >= (row_count -1)) ||
527                                                     ((frq_sec != -1) && (date.before(limit_d) == false))) {
528                                                         ret_val->add(calc);
529                                                         delete(calc);
530                                                         calc    = data->clone();
531                                                         if (limit_d != NULL) {
532                                                                 delete(limit_d);
533                                                         }
534                                                         limit_d         = data->get_date().clone();
535                                                         limit_d->min    = 0;
536                                                         limit_d->sec    = 0;
537                                                         limit_d->inc_seconds(frq_sec);
538                                                 }
539                                                 delete(data);
540                                         }
541                                 }
542                                 if (calc != NULL) {
543                                         delete(calc);
544                                         calc    = NULL;
545                                 }
546                                 if (limit_d != NULL) {
547                                         delete(limit_d);
548                                 }
549                         }
550                 }
551         }
552         return ret_val;
553 }
554
555 plp::DataRange *StoreDay::get_max(EnumSummaryPeriod period_type_param) {
556         DataRange       *ret_val;
557
558         ret_val = get_max_or_min(period_type_param, true);
559         return ret_val;
560 }
561
562 plp::DataRange *StoreDay::get_min(EnumSummaryPeriod period_type_param) {
563         DataRange       *ret_val;
564
565         ret_val = get_max_or_min(period_type_param, false);
566         return ret_val;
567 }
568
569 DataRange *StoreDay::get_oldest_and_latest_data(string fname_param) {
570         DataRange       *ret_val;
571         ifstream        in;
572         Data            *o_data;
573         Data            *n_data;
574         string          latest;
575         int             row_count;
576         string          line;
577         string          prev_line;
578
579         ret_val = NULL;
580         o_data  = NULL;
581         n_data  = NULL;
582         if (store_data != NULL) {
583                 row_count       = store_data->get_count();
584                 if (row_count > 0) {
585                         o_data  = store_data->get(0);
586                         n_data  = store_data->get(row_count - 1);
587                 }
588         }
589         else {
590                 if (range_data != NULL) {
591                         row_count       = range_data->get_count();
592                         if (row_count > 0) {
593                                 o_data  = range_data->get(0);
594                                 n_data  = range_data->get(row_count - 1);
595                         }
596                 }
597                 else {
598                         in.open(fname_param.c_str());
599                         if (in.is_open() == true) {
600                                 while (in.eof() == false) {
601                                         getline(in, line);
602                                         if (line.empty() == false) {
603                                                 if (o_data == NULL) {
604                                                         o_data  = Data::parse_string(line);
605                                                 }
606                                                 prev_line       = line;
607                                         }
608                                 }
609                                 if (prev_line.empty() == false) {
610                                         n_data  = Data::parse_string(prev_line);
611                                 }
612                         }
613                 }
614         }
615         if ((o_data != NULL) &&
616             (n_data != NULL)) {
617                 ret_val = new DataRange(o_data);
618                 ret_val->add(n_data);
619                 if (range_data != NULL) {
620                         range_data      = new DataRange(o_data);
621                         range_data->add(n_data);
622                 }
623         }
624         if (o_data != NULL) {
625                 delete(o_data);
626         }
627         if (n_data != NULL) {
628                 delete(n_data);
629         }
630         return ret_val;
631 }
632
633 DataRange *StoreDay::get_oldest_and_latest_data() {
634         return get_oldest_and_latest_data(store_fname);
635 }
636
637 Data *StoreDay::get_oldest_data() {
638         int             row_count;
639         Data            *ret_val;
640         DataRange       *dr;
641
642         ret_val = NULL;
643         dr      = get_oldest_and_latest_data();
644         if (dr != NULL) {
645                 row_count       = dr->get_count();
646                 if (row_count >= 1) {
647                         ret_val = dr->get(0);
648                 }
649                 delete(dr);
650         }
651         return ret_val;
652 }
653
654 Data *StoreDay::get_latest_data() {
655         int             row_count;
656         Data            *ret_val;
657         DataRange       *dr;
658
659         ret_val = NULL;
660         dr      = get_oldest_and_latest_data();
661         if (dr != NULL) {
662                 row_count       = dr->get_count();
663                 if (row_count == 2) {
664                         ret_val = dr->get(1);
665                 }
666                 delete(dr);
667         }
668         return ret_val;
669 }
670
671 bool StoreDay::data_day_scan_days_in_month(string dev_id_param,
672                                 Date *new_date,
673                                 Date *max_date) {
674         bool    ret_val;
675         string  fname;
676
677         ret_val = false;
678         while((ret_val == false) &&
679               (new_date->before(max_date))) {
680                 new_date->next_day();
681                 fname   = get_file_name(dev_id_param, new_date);
682                 if (exist(fname, false) == true) {
683                         ret_val = true;
684                         break;
685                 }
686                 if (new_date->is_last_day_of_month() == true) {
687                         break;
688                 }
689         }
690         return ret_val;
691 }
692
693 bool StoreDay::data_day_scan_month_in_year(string dev_id_param,
694                                 Date *new_date,
695                                 Date *max_date) {
696         bool    ret_val;
697
698         ret_val = false;
699         // next scan months dir existence under the first year
700         while((ret_val == false) &&
701               (new_date->before(max_date))) {
702                 new_date->next_month();
703                 if (exist_in_month(dev_id_param,
704                                 new_date,
705                                 false)) {
706                         ret_val = data_day_scan_days_in_month(dev_id_param,
707                                                         new_date,
708                                                         max_date);
709                         if (ret_val == true)
710                                 break;
711                 }
712                 if (new_date->month == 12)
713                         break;
714         }
715         return ret_val;
716 }
717
718 bool StoreDay::data_day_scan_years(string dev_id_param,
719                         Date *new_date,
720                         Date *max_date) {
721         bool    ret_val;
722
723         ret_val = false;
724         while((ret_val == false) &&
725               (new_date->before(max_date))) {
726                 new_date->next_year();
727                 if (exist_in_year(dev_id_param,
728                                 new_date,
729                                 false)) {
730                         ret_val = data_day_scan_month_in_year(dev_id_param,
731                                                         new_date,
732                                                         max_date);
733                         if (ret_val == true)
734                                 break;
735                 }
736         }
737         return ret_val;
738 }
739
740 bool StoreDay::get_next_date_with_data(std::string dev_id_param,
741                                 plp::Date *next_date,
742                                 plp::Date *max_date) {
743         bool    ret_val;
744         Date    *new_date;
745         string  fname;
746         string  dirname;
747
748         new_date        = next_date->clone();
749         // scan first dates in current month
750         ret_val         = data_day_scan_days_in_month(dev_id_param,
751                                                 new_date,
752                                                 max_date);
753         if (ret_val == false) {
754                 ret_val = data_day_scan_month_in_year(dev_id_param,
755                                                 new_date,
756                                                 max_date);
757                 if (ret_val == false) {
758                         ret_val = data_day_scan_years(dev_id_param,
759                                                 new_date,
760                                                 max_date);
761                 }
762         }
763         if (ret_val == true)
764                 new_date->copy(next_date);
765         else
766                 max_date->copy(next_date);
767         delete(new_date);
768         return ret_val;
769 }