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