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