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