]> pilppa.org Git - libplp.git/blob - src/StoreCache.cc
fix potential error from uninitialized variable
[libplp.git] / src / StoreCache.cc
1 /*
2  * StoreCache.cc
3  *
4  *  Created on: Jan 6, 2011
5  *      Author: lamikr
6  */
7 #include <sstream>
8 #include <fstream>
9
10 #include <unistd.h>
11
12 #include "log.h"
13 #include "Store.hh"
14 #include "StoreCache.hh"
15 #include "StoreDay.hh"
16 #include "DeviceConfig.hh"
17 #include "FileUtil.hh"
18
19 using namespace std;
20 using namespace plp;
21
22 StoreCache::StoreCache(string device_id_param,
23         Date *date_time_param): Store(device_id_param, date_time_param) {
24 }
25
26 StoreCache::~StoreCache() {
27 }
28
29 string StoreCache::get_dir_name(string device_id_param,
30                                 Date *date_time_param,
31                                 EnumSummaryPeriod period_type_param,
32                                 EnumSummaryCalculationType calc_type_param) {
33         string  ret_val;
34         char    buffer[30];
35         string  bd_name;
36         string  period_name;
37         string  calc_type;
38
39         period_name     = DataSummary::get_summary_period_name(period_type_param);
40         calc_type       = DataSummary::get_summary_calculation_name(calc_type_param);
41
42         bd_name = DeviceConfig::get_base_dir_name();
43         bd_name = FileUtil::concat_paths(bd_name, CACHE_DIR_NAME);
44         bd_name = FileUtil::concat_paths(bd_name, device_id_param);
45         bd_name = FileUtil::concat_paths(bd_name, period_name);
46         bd_name = FileUtil::concat_paths(bd_name, calc_type);
47         if (period_type_param == PERIOD_YEARLY) {
48                 ret_val = bd_name;
49         }
50         else if (period_type_param == PERIOD_MONTHLY) {
51                 snprintf(buffer, 30, "%d", date_time_param->year);
52                 ret_val = bd_name + "/" + buffer;
53         }
54         else {
55                 snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
56                 ret_val = bd_name + "/" + buffer;
57         }
58         return ret_val;
59 }
60
61 string StoreCache::get_file_name(string device_id_param,
62                                 Date *date_time_param,
63                                 EnumSummaryPeriod period_type_param,
64                                 EnumSummaryCalculationType calc_type_param) {
65         string  ret_val;
66         string  fname;
67         char    buffer[30];
68
69         if (period_type_param == PERIOD_YEARLY) {
70                 snprintf(buffer, 30, "%d", date_time_param->year);
71         }
72         else if (period_type_param == PERIOD_MONTHLY) {
73                 snprintf(buffer, 30, "%d-%02d",
74                         date_time_param->year,
75                         date_time_param->month);
76         }
77         else {
78                 snprintf(buffer, 30, "%d-%02d-%02d",
79                         date_time_param->year,
80                         date_time_param->month,
81                         date_time_param->day);
82         }
83         fname   = buffer;
84         fname   = fname + DATAFILE_SUFFIX;
85         ret_val = get_dir_name(device_id_param, date_time_param, period_type_param, calc_type_param);
86         ret_val = FileUtil::concat_paths(ret_val, fname);
87         return ret_val;
88 }
89
90 plp::Date *StoreCache::get_scanning_limit_date(EnumSummaryPeriod period_type_param) {
91         Data    *cur_data;;
92         Date    *ret_val;
93
94         cur_data        = get_latest_data(date, device_id, period_type_param);
95         if (cur_data != NULL) {
96                 ret_val = cur_data->get_date().clone();
97                 ret_val->next_second();
98                 delete(cur_data);
99                 cur_data        = NULL;
100         }
101         else {
102                 ret_val = date->clone();
103                 if (period_type_param == PERIOD_YEARLY) {
104                         ret_val->next_year();
105                 }
106                 else {
107                         ret_val->next_month();
108                 }
109         }
110         return ret_val;
111 }
112
113 DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
114         int             row_count;
115         DataRange       *ret_val;
116         Data            *dta;
117         string          fname;
118
119         ret_val = NULL;
120         fname   = get_file_name(device_id,
121                                 date,
122                                 period_type_param,
123                                 MEAN);
124         if (store_data == NULL) {
125                 if (access(fname.c_str(), R_OK) == 0) {
126                         load(fname);
127                 }
128         }
129         if (store_data != NULL) {
130                 row_count       = store_data->get_count();
131                 if (row_count > 0) {
132                         ret_val = new DataRange();
133                         dta     = store_data->get(0);
134                         ret_val->add(dta);
135                         delete(dta);
136                 }
137         }
138         if (ret_val == NULL) {
139                 switch(period_type_param) {
140                         case PERIOD_YEARLY:
141                         case PERIOD_MONTHLY:
142                         {
143                                         Data            *cur_data;
144                                         Data            *res_data;
145                                         Date            *cur_date;
146                                         Date            *max_date;
147                                         int             ii;
148                                         int             cnt;
149                                         int             val_cnt;
150                                         DataRange       *dr;
151                                         Store           *store;
152
153                                         cur_date        = date->clone();
154                                         max_date        = get_scanning_limit_date(period_type_param);
155                                         cur_data        = NULL;
156                                         res_data        = NULL;
157                                         cnt             = 0;
158                                         val_cnt         = 0;
159                                         dr              = NULL;
160                                         while(cur_date->before(max_date)) {
161                                                 if (period_type_param == PERIOD_YEARLY) {
162                                                         store   = new StoreCache(device_id, cur_date);
163                                                         dr      = store->get_mean(PERIOD_MONTHLY);
164                                                 }
165                                                 else {
166                                                         if (StoreDay::exist(device_id, cur_date, false)) {
167                                                                 store   = new StoreDay(device_id, cur_date);
168                                                                 dr      = store->get_mean(PERIOD_DAILY);
169                                                         }
170                                                         if (dr == NULL) {
171                                                                 // data not found for that day, try to find next date containing data
172                                                                 StoreDay::get_next_date_with_data(device_id,
173                                                                                         cur_date,
174                                                                                         max_date);
175                                                                 continue;
176                                                         }
177                                                 }
178                                                 if (dr != NULL) {
179                                                         cur_data        = dr->get_first();
180                                                         if (cur_data != NULL) {
181                                                                 cnt++;
182                                                                 if (res_data == NULL) {
183                                                                         res_data        = cur_data;
184                                                                         val_cnt         = res_data->get_value_count();
185                                                                 }
186                                                                 else {
187                                                                         for (ii = 0; ii < val_cnt; ii++) {
188                                                                                 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
189                                                                         }
190                                                                         delete(cur_data);
191                                                                 }
192                                                         }
193                                                         delete(dr);
194                                                 }
195                                                 delete(store);
196                                                 if (period_type_param == PERIOD_YEARLY) {
197                                                         cur_date->next_month();
198                                                 }
199                                                 else {
200                                                         cur_date->next_day();
201                                                 }
202                                         }
203                                         if ((res_data != NULL) &&
204                                             (cnt > 0)) {
205                                                 for (ii = 0; ii < val_cnt; ii++) {
206                                                         res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
207                                                 }
208                                                 ret_val = new DataRange(res_data);
209                                                 save(fname, ret_val, 4);
210                                                 delete(res_data);
211                                         }
212                                         delete(cur_date);
213                                         delete(max_date);
214                                 }
215                                 break;
216                         case PERIOD_DAILY:
217                         case PERIOD_HOURLY:
218                         case PERIOD_MINUTELY:
219                         case PERIOD_SECONDLY:
220                                 if (StoreDay::exist(device_id, date, false)) {
221                                         StoreDay        *store;
222
223                                         store   = new StoreDay(device_id, date);
224                                         ret_val = store->get_mean(period_type_param);
225                                         if ((ret_val != NULL) &&
226                                             (period_type_param != PERIOD_MINUTELY) &&
227                                             (period_type_param != PERIOD_SECONDLY)) {
228                                                 // no need cache second or minute data
229                                                 save(fname, ret_val, 4);
230                                         }
231                                         delete(store);
232                                 }
233                                 break;
234                 }
235         }
236         return ret_val;
237 }
238
239 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
240         int             row_count;
241         DataRange       *ret_val;
242         Data            *dta;
243         string          fname;
244         Store           *store;
245
246         ret_val = NULL;
247         fname   = get_file_name(device_id,
248                                 date,
249                                 period_type_param,
250                                 SUM);
251         if (store_data == NULL) {
252                 if (access(fname.c_str(), R_OK) == 0) {
253                         load(fname);
254                 }
255         }
256         if (store_data != NULL) {
257                 row_count       = store_data->get_count();
258                 if (row_count > 0) {
259                         ret_val = new DataRange();
260                         dta     = store_data->get(0);
261                         ret_val->add(dta);
262                         delete(dta);
263                 }
264         }
265         if (ret_val == NULL) {
266                 switch(period_type_param) {
267                         case PERIOD_YEARLY:
268                         case PERIOD_MONTHLY: {
269                                         Data            *cur_data;
270                                         Data            *res_data;
271                                         Date            *cur_date;
272                                         Date            *max_date;
273                                         int             ii;
274                                         int             cnt;
275                                         int             val_cnt;
276                                         DataRange       *dr;
277
278                                         cur_date        = date->clone();
279                                         max_date        = get_scanning_limit_date(period_type_param);
280                                         cur_data        = NULL;
281                                         res_data        = NULL;
282                                         cnt             = 0;
283                                         while(cur_date->before(max_date)) {
284                                                 dr      = NULL;
285                                                 store   = NULL;
286                                                 if (period_type_param == PERIOD_YEARLY) {
287                                                         store   = new StoreCache(device_id, cur_date);
288                                                         dr      = store->get_sum(PERIOD_MONTHLY);
289                                                 }
290                                                 else {
291                                                         if (StoreDay::exist(device_id, cur_date, false)) {
292                                                                 store   = new StoreDay(device_id, cur_date);
293                                                                 dr      = store->get_sum(PERIOD_DAILY);
294                                                         }
295                                                         if (dr == NULL) {
296                                                                 // data not found for that day, try to find next date containing data
297                                                                 StoreDay::get_next_date_with_data(device_id,
298                                                                                                 cur_date,
299                                                                                                 max_date);
300                                                                 continue;
301                                                         }
302                                                 }
303                                                 if (dr != NULL) {
304                                                         cur_data        = dr->get_first();
305                                                         if (cur_data != NULL) {
306                                                                 cnt++;
307                                                                 if (res_data == NULL) {
308                                                                         res_data        = cur_data;
309                                                                 }
310                                                                 else {
311                                                                         val_cnt = res_data->get_value_count();
312                                                                         for (ii = 0; ii < val_cnt; ii++) {
313                                                                                 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
314                                                                         }
315                                                                         delete(cur_data);
316                                                                 }
317                                                         }
318                                                         delete(dr);
319                                                 }
320                                                 if (store != NULL)
321                                                         delete(store);
322                                                 if (period_type_param == PERIOD_YEARLY) {
323                                                         cur_date->next_month();
324                                                 }
325                                                 else {
326                                                         cur_date->next_day();
327                                                 }
328                                         }
329                                         if ((res_data != NULL) &&
330                                             (cnt > 0)) {
331                                                 ret_val = new DataRange(res_data);
332                                                 save(fname, ret_val, 4);
333                                                 delete(res_data);
334                                         }
335                                         delete(cur_date);
336                                         delete(max_date);
337                                 }
338                                 break;
339                         case PERIOD_DAILY:
340                         case PERIOD_HOURLY:
341                         case PERIOD_MINUTELY:
342                         case PERIOD_SECONDLY:
343                                 if (StoreDay::exist(device_id, date, false)) {
344                                         store   = new StoreDay(device_id, date);
345                                         ret_val = store->get_sum(period_type_param);
346                                         if ((ret_val != NULL) &&
347                                             (period_type_param != PERIOD_MINUTELY) &&
348                                             (period_type_param != PERIOD_SECONDLY)) {
349                                                 // no need cache second or minute data
350                                                 save(fname, ret_val, 4);
351                                         }
352                                         delete(store);
353                                 }
354                                 break;
355                 }
356         }
357         return ret_val;
358 }
359
360 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
361         int             row_count;
362         DataRange       *ret_val;
363         Data            *dta;
364         string          fname;
365         StoreDay        *store;
366
367         ret_val = NULL;
368         fname   = get_file_name(device_id,
369                                 date,
370                                 period_type_param,
371                                 DELTA);
372         if (store_data == NULL) {
373                 if (access(fname.c_str(), R_OK) == 0) {
374                         // read from cache file
375                         load(fname);
376                 }
377         }
378         if (store_data != NULL) {
379                 row_count       = store_data->get_count();
380                 if (row_count > 0) {
381                         ret_val = new DataRange();
382                         dta     = store_data->get(0);
383                         ret_val->add(dta);
384                         delete(dta);
385                 }
386         }
387         if (ret_val == NULL) {
388                 switch(period_type_param) {
389                         case PERIOD_YEARLY: {
390                                         Data    *first_data;
391                                         Data    *last_data;
392                                         int     ii;
393                                         int     cnt;
394
395                                         first_data      = get_oldest_data(date, device_id, PERIOD_YEARLY);
396                                         if (first_data != NULL) {
397                                                 last_data       = get_latest_data(date, device_id, PERIOD_YEARLY);
398                                                 if (last_data != NULL) {
399                                                         ret_val         = new DataRange();
400                                                         cnt             = last_data->get_value_count();
401                                                         for (ii = 0; ii < cnt; ii++) {
402                                                                 last_data->value_arr[ii]        = last_data->value_arr[ii] - first_data->value_arr[ii];
403                                                         }
404                                                         ret_val->add(last_data);
405                                                         delete(last_data);
406                                                 }
407                                                 delete(first_data);
408                                                 save(fname, ret_val, 4);
409                                         }
410                                         else {
411                                                 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
412                                         }
413                                 }
414                                 break;
415                         case PERIOD_MONTHLY: {
416                                         Data    *first_data;
417                                         Data    *last_data;
418                                         Data    *cur_data;
419                                         Date    *cur_date;
420                                         Date    *max_date;
421                                         int     ii;
422                                         int     cnt;
423
424                                         cur_date        = date->clone();
425                                         max_date        = date->clone();
426                                         max_date->next_month();
427                                         first_data      = NULL;
428                                         last_data       = NULL;
429                                         while(cur_date->before(max_date)) {
430                                                 if (StoreDay::exist(device_id,
431                                                                 cur_date,
432                                                                 false)) {
433                                                         store   = new StoreDay(device_id, cur_date);
434                                                         if (first_data == NULL) {
435                                                                 cur_data        = store->get_oldest_data();
436                                                                 if (cur_data != NULL) {
437                                                                         first_data      = cur_data->clone();
438                                                                         last_data       = cur_data->clone();
439                                                                         delete(cur_data);
440                                                                 }
441                                                         }
442                                                         cur_data        = store->get_latest_data();
443                                                         if (cur_data != NULL) {
444                                                                 if (last_data != NULL) {
445                                                                         delete(last_data);
446                                                                 }
447                                                                 last_data       = cur_data;
448                                                         }
449                                                         delete(store);
450                                                         cur_date->next_day();
451                                                 }
452                                                 else {
453                                                         // data not found for that day, try to find next date containing data
454                                                         StoreDay::get_next_date_with_data(device_id,
455                                                                                 cur_date,
456                                                                                 max_date);
457                                                 }
458                                         }
459                                         delete(cur_date);
460                                         delete(max_date);
461                                         if (first_data != NULL) {
462                                                 if (last_data == NULL) {
463                                                         last_data       = first_data->clone();
464                                                 }
465                                                 cnt     = last_data->get_value_count();
466                                                 for (ii = 0; ii < cnt; ii++) {
467                                                         last_data->value_arr[ii]        = last_data->value_arr[ii] - first_data->value_arr[ii];
468                                                 }
469                                                 cur_date        = first_data->get_date().clone();
470                                                 last_data->set_date(cur_date);
471                                                 delete(cur_date);
472                                                 ret_val = new DataRange(last_data);
473                                                 delete(first_data);
474                                                 delete(last_data);
475                                                 save(fname, ret_val, 4);
476                                         }
477                                 }
478                                 break;
479                         case PERIOD_DAILY:
480                         case PERIOD_HOURLY:
481                         case PERIOD_MINUTELY:
482                         case PERIOD_SECONDLY:
483                                 if (StoreDay::exist(device_id, date, false)) {
484                                         store   = new StoreDay(device_id, date);
485                                         ret_val = store->get_delta(period_type_param);
486                                         if ((period_type_param != PERIOD_MINUTELY) ||
487                                             (period_type_param != PERIOD_SECONDLY)) {
488                                                 // no need cache second or minute data
489                                                 save(fname, ret_val, 4);
490                                         }
491                                         delete(store);
492                                 }
493                                 break;
494                 }
495         }
496         return ret_val;
497 }
498
499 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
500         int             row_count;
501         DataRange       *ret_val;
502         Data            *dta;
503         string          fname;
504         Store           *store;
505
506         ret_val = NULL;
507         fname   = get_file_name(device_id,
508                                 date,
509                                 period_type_param,
510                                 MAX);
511         if (store_data == NULL) {
512                 if (access(fname.c_str(), R_OK) == 0) {
513                         load(fname);
514                 }
515         }
516         if (store_data != NULL) {
517                 row_count       = store_data->get_count();
518                 if (row_count > 0) {
519                         ret_val = new DataRange();
520                         dta     = store_data->get(0);
521                         ret_val->add(dta);
522                         delete(dta);
523                 }
524         }
525         if (ret_val == NULL) {
526                 switch(period_type_param) {
527                         case PERIOD_YEARLY:
528                         case PERIOD_MONTHLY: {
529                                         Data            *cur_data;
530                                         Data            *res_data;
531                                         Date            *cur_date;
532                                         Date            *max_date;
533                                         int             ii;
534                                         int             cnt;
535                                         int             val_cnt;
536                                         DataRange       *dr;
537
538                                         cur_date        = date->clone();
539                                         max_date        = get_scanning_limit_date(period_type_param);
540                                         cur_data        = NULL;
541                                         res_data        = NULL;
542                                         cnt             = 0;
543                                         while(cur_date->before(max_date)) {
544                                                 if (period_type_param == PERIOD_YEARLY) {
545                                                         store   = new StoreCache(device_id, cur_date);
546                                                         dr      = store->get_max(PERIOD_MONTHLY);
547                                                 }
548                                                 else {
549                                                         if (StoreDay::exist(device_id, cur_date, false)) {
550                                                                 store   = new StoreDay(device_id, cur_date);
551                                                                 dr      = store->get_max(PERIOD_DAILY);
552                                                         }
553                                                         else {
554                                                                 StoreDay::get_next_date_with_data(device_id,
555                                                                                                 cur_date,
556                                                                                                 max_date);
557                                                                 continue;
558                                                         }
559                                                 }
560                                                 if (dr != NULL) {
561                                                         cur_data        = dr->get_first();
562                                                         if (cur_data != NULL) {
563                                                                 cnt++;
564                                                                 if (res_data == NULL) {
565                                                                         res_data        = cur_data;
566                                                                 }
567                                                                 else {
568                                                                         val_cnt = res_data->get_value_count();
569                                                                         int changed = 0;
570                                                                         for (ii = 0; ii < val_cnt; ii++) {
571                                                                                 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
572                                                                                         res_data->value_arr[ii] = cur_data->value_arr[ii];
573                                                                                         changed = 1;
574                                                                                 }
575                                                                         }
576                                                                         if (changed == 1) {
577                                                                                 Date new_date;
578
579                                                                                 new_date        = cur_data->get_date();
580                                                                                 res_data->set_date(&new_date);
581                                                                         }
582                                                                         delete(cur_data);
583                                                                 }
584                                                         }
585                                                         delete(dr);
586                                                 }
587                                                 delete(store);
588                                                 if (period_type_param == PERIOD_YEARLY) {
589                                                         cur_date->next_month();
590                                                 }
591                                                 else {
592                                                         cur_date->next_day();
593                                                 }
594                                         }
595                                         if ((res_data != NULL) &&
596                                             (cnt > 0)) {
597                                                 ret_val = new DataRange(res_data);
598                                                 save(fname, ret_val, 4);
599                                                 delete(res_data);
600                                         }
601                                         delete(cur_date);
602                                         delete(max_date);
603                                 }
604                                 break;
605                         case PERIOD_DAILY:
606                         case PERIOD_HOURLY:
607                         case PERIOD_MINUTELY:
608                         case PERIOD_SECONDLY:
609                                 if (StoreDay::exist(device_id, date, false)) {
610                                         store   = new StoreDay(device_id, date);
611                                         ret_val = store->get_max(period_type_param);
612                                         if ((period_type_param != PERIOD_MINUTELY) ||
613                                             (period_type_param != PERIOD_SECONDLY)) {
614                                                 // no need cache second or minute data
615                                                 save(fname, ret_val, 4);
616                                         }
617                                         delete(store);
618                                 }
619                                 break;
620                 }
621         }
622         return ret_val;
623 }
624
625 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
626         int             row_count;
627         DataRange       *ret_val;
628         Data            *dta;
629         string          fname;
630         Store           *store;
631
632         ret_val = NULL;
633         fname   = get_file_name(device_id,
634                                 date,
635                                 period_type_param,
636                                 MIN);
637         if (store_data == NULL) {
638                 if (access(fname.c_str(), R_OK) == 0) {
639                         load(fname);
640                 }
641         }
642         if (store_data != NULL) {
643                 row_count       = store_data->get_count();
644                 if (row_count > 0) {
645                         ret_val = new DataRange();
646                         dta     = store_data->get(0);
647                         ret_val->add(dta);
648                         delete(dta);
649                 }
650         }
651         if (ret_val == NULL) {
652                 switch(period_type_param) {
653                         case PERIOD_YEARLY:
654                         case PERIOD_MONTHLY: {
655                                         Data            *cur_data;
656                                         Data            *res_data;
657                                         Date            *cur_date;
658                                         Date            *max_date;
659                                         int             ii;
660                                         int             cnt;
661                                         int             val_cnt;
662                                         DataRange       *dr;
663
664                                         cur_date        = date->clone();
665                                         max_date        = get_scanning_limit_date(period_type_param);
666                                         cur_data        = NULL;
667                                         res_data        = NULL;
668                                         cnt             = 0;
669                                         while(cur_date->before(max_date)) {
670                                                 if (period_type_param == PERIOD_YEARLY) {
671                                                         store   = new StoreCache(device_id, cur_date);
672                                                         dr      = store->get_min(PERIOD_MONTHLY);
673                                                 }
674                                                 else {
675                                                         if (StoreDay::exist(device_id, cur_date, false)) {
676                                                                 store   = new StoreDay(device_id, cur_date);
677                                                                 dr      = store->get_min(PERIOD_DAILY);
678                                                         }
679                                                         else {
680                                                                 StoreDay::get_next_date_with_data(device_id,
681                                                                                                 cur_date,
682                                                                                                 max_date);
683                                                                 continue;
684                                                         }
685                                                 }
686                                                 if (dr != NULL) {
687                                                         cur_data        = dr->get_first();
688                                                         if (cur_data != NULL) {
689                                                                 cnt++;
690                                                                 if (res_data == NULL) {
691                                                                         res_data        = cur_data;
692                                                                 }
693                                                                 else {
694                                                                         val_cnt = res_data->get_value_count();
695                                                                         int changed = 0;
696                                                                         for (ii = 0; ii < val_cnt; ii++) {
697                                                                                 if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
698                                                                                         res_data->value_arr[ii] = cur_data->value_arr[ii];
699                                                                                         changed = 1;
700                                                                                 }
701                                                                         }
702                                                                         if (changed == 1) {
703                                                                                 Date new_date;
704
705                                                                                 new_date        = cur_data->get_date();
706                                                                                 res_data->set_date(&new_date);
707                                                                         }
708                                                                         delete(cur_data);
709                                                                 }
710                                                         }
711                                                         delete(dr);
712                                                 }
713                                                 delete(store);
714                                                 if (period_type_param == PERIOD_YEARLY) {
715                                                         cur_date->next_month();
716                                                 }
717                                                 else {
718                                                         cur_date->next_day();
719                                                 }
720                                         }
721                                         if ((res_data != NULL) &&
722                                             (cnt > 0)) {
723                                                 ret_val = new DataRange(res_data);
724                                                 save(fname, ret_val, 4);
725                                                 delete(res_data);
726                                         }
727                                         delete(cur_date);
728                                         delete(max_date);
729                                 }
730                                 break;
731                         case PERIOD_DAILY:
732                         case PERIOD_HOURLY:
733                         case PERIOD_MINUTELY:
734                         case PERIOD_SECONDLY:
735                                 if (StoreDay::exist(device_id, date, false)) {
736                                         store   = new StoreDay(device_id, date);
737                                         ret_val = store->get_min(period_type_param);
738                                         if ((period_type_param != PERIOD_MINUTELY) ||
739                                             (period_type_param != PERIOD_SECONDLY)) {
740                                                 // no need cache second or minute data
741                                                 save(fname, ret_val, 4);
742                                         }
743                                         delete(store);
744                                 }
745                                 break;
746                 }
747         }
748         return ret_val;
749 }
750
751 void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
752         string          line;
753         Data            *data;
754         ofstream        *ostream;
755         int             ii;
756         int             cnt;
757
758         cnt     = datarange_param->get_count();
759         ostream =  NULL;
760         //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
761         ostream = FileUtil::open_for_writing(fname_param.c_str());
762         if ((ostream != NULL) &&
763             (ostream->is_open() == true)) {
764                 // TODO: add mutex to protect string_list while it's read and emptied
765                 for(ii = 0; ii < cnt; ii++) {
766                         data    = datarange_param->get(ii);
767                         if (data != NULL) {
768                                 line    = data->to_string(decimal_count_param);
769                                 if (line.length() > 0) {
770                                         *ostream << line << endl;
771                                 }
772                                 delete(data);
773                         }
774                 }
775         }
776         else {
777                 log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
778         }
779         if (ostream != NULL) {
780                 ostream->close();
781                 delete(ostream);
782         }
783 }
784
785 Data *StoreCache::get_oldest_data(Date *date_param,
786                         string device_id_param,
787                         EnumSummaryPeriod period_type_param) {
788         int             size;
789         unsigned int    ii;
790         string          year_dr;
791         string          mon_dr;
792         vector<string>  mon_vcr;
793         vector<string>  dta_vcr;
794         string          f_name;
795         StoreDay        *store;
796         Data            *ret_val;
797         string          device_dir;
798         char            buffer[30];
799         string          year_name;
800
801         ret_val = NULL;
802         if (period_type_param == PERIOD_YEARLY) {
803                 snprintf(buffer, 30, "%d", date_param->year);
804                 year_name.append(buffer);
805                 device_dir      = DeviceConfig::get_base_dir_name();
806                 device_dir      = FileUtil::concat_paths(device_dir, device_id_param);
807                 year_dr = FileUtil::concat_paths(device_dir, year_name);
808                 mon_vcr = FileUtil::get_subdirectories(year_dr);
809                 for (ii = 0; ii < mon_vcr.size(); ii++) {
810                         mon_dr  = mon_vcr.at(ii);
811                         mon_dr  = FileUtil::concat_paths(year_dr, mon_dr);
812                         // scan data files from month dir
813                         dta_vcr = FileUtil::get_data_files(mon_dr);
814                         size    = dta_vcr.size();
815                         if (size > 0) {
816                                 f_name  = dta_vcr.at(0);
817                                 f_name  = FileUtil::concat_paths(mon_dr, f_name);
818                                 store   = new StoreDay(f_name);
819                                 ret_val = store->get_oldest_data();
820                                 delete(store);
821                                 break;
822                         }
823                 }
824         }
825         else if (period_type_param == PERIOD_MONTHLY) {
826                 ret_val         = NULL;
827                 snprintf(buffer, 30, "%d", date_param->year);
828                 year_name.append(buffer);
829                 device_dir      = DeviceConfig::get_base_dir_name();
830                 device_dir      = FileUtil::concat_paths(device_dir, device_id_param);
831                 year_dr         = FileUtil::concat_paths(device_dir, year_name);
832                 snprintf(buffer, 30, "%02d", date_param->month);
833                 mon_dr.append(buffer);
834                 mon_dr          = FileUtil::concat_paths(year_dr, mon_dr);
835                 // scan data files from month dir
836                 dta_vcr         = FileUtil::get_data_files(mon_dr);
837                 size            = dta_vcr.size();
838                 if (size > 0) {
839                         f_name  = dta_vcr.at(0);
840                         f_name  = FileUtil::concat_paths(mon_dr, f_name);
841                         store   = new StoreDay(f_name);
842                         ret_val = store->get_oldest_data();
843                         delete(store);
844                 }
845
846         }
847         else {
848                 store   = new StoreDay(device_id_param, date_param);
849                 ret_val = store->get_oldest_data();
850                 delete(store);
851         }
852         return ret_val;
853 }
854
855 Data *StoreCache::get_latest_data(Date *date_param,
856                         string device_id_param,
857                         EnumSummaryPeriod period_type_param) {
858         int             ii;
859         string          mon_dr;
860         vector<string>  mon_vcr;
861         vector<string>  dta_vcr;
862         string          f_name;
863         StoreDay        *store;
864         Data            *ret_val;
865         string          year_dr;
866         int             size;
867         string          device_dir;
868         char            buffer[30];
869         string          year_name;
870
871         ret_val = NULL;
872         if (period_type_param == PERIOD_YEARLY) {
873                 snprintf(buffer, 30, "%d", date_param->year);
874                 year_name.append(buffer);
875                 device_dir      = DeviceConfig::get_base_dir_name();
876                 device_dir      = FileUtil::concat_paths(device_dir, device_id_param);
877                 year_dr = FileUtil::concat_paths(device_dir, year_name);
878                 mon_vcr = FileUtil::get_subdirectories(year_dr);
879                 for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
880                         mon_dr  = mon_vcr.at(ii);
881                         mon_dr  = FileUtil::concat_paths(year_dr, mon_dr);
882                         // scan data files from month dir
883                         dta_vcr = FileUtil::get_data_files(mon_dr);
884                         size    = dta_vcr.size();
885                         if (size > 0) {
886                                 f_name  = dta_vcr.at(size - 1);
887                                 f_name  = FileUtil::concat_paths(mon_dr, f_name);
888                                 store   = new StoreDay(f_name);
889                                 ret_val = store->get_latest_data();
890                                 delete(store);
891                                 break;
892                         }
893                 }
894         }
895         else if (period_type_param == PERIOD_MONTHLY) {
896                 ret_val         = NULL;
897                 snprintf(buffer, 30, "%d", date_param->year);
898                 year_name.append(buffer);
899                 device_dir      = DeviceConfig::get_base_dir_name();
900                 device_dir      = FileUtil::concat_paths(device_dir, device_id_param);
901                 year_dr         = FileUtil::concat_paths(device_dir, year_name);
902                 snprintf(buffer, 30, "%02d", date_param->month);
903                 mon_dr.append(buffer);
904                 mon_dr          = FileUtil::concat_paths(year_dr, mon_dr);
905                 // scan data files from month dir
906                 dta_vcr         = FileUtil::get_data_files(mon_dr);
907                 size            = dta_vcr.size();
908                 if (size > 0) {
909                         f_name  = dta_vcr.at(size - 1);
910                         f_name  = FileUtil::concat_paths(mon_dr, f_name);
911                         store   = new StoreDay(f_name);
912                         ret_val = store->get_latest_data();
913                         delete(store);
914                 }
915
916         }
917         else {
918                 store   = new StoreDay(device_id_param, date_param);
919                 ret_val = store->get_latest_data();
920                 delete(store);
921         }
922         return ret_val;
923 }