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