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