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