4 * Created on: Jan 6, 2011
12 #include "StoreCache.hh"
13 #include "StoreDay.hh"
14 #include "DeviceConfig.hh"
15 #include "FileUtil.hh"
20 StoreCache::StoreCache(string device_id_param,
21 Date *date_time_param): Store(device_id_param, date_time_param) {
24 StoreCache::~StoreCache() {
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) {
35 bd_name = DeviceConfig::get_base_dir_name();
36 bd_name = FileUtil::concat_paths(bd_name, CACHE_DIR_NAME);
37 bd_name = FileUtil::concat_paths(bd_name, device_id_param);
38 bd_name = FileUtil::concat_paths(bd_name, SUMMARY_PERIOD_NAMES_ARRAY[period_type_param]);
39 bd_name = FileUtil::concat_paths(bd_name, CALCULATION_TYPE_NAMES_ARRAY[calc_type_param]);
40 if (period_type_param == PERIOD_YEARLY) {
43 else if (period_type_param == PERIOD_MONTHLY) {
44 snprintf(buffer, 30, "%d", date_time_param->year);
45 ret_val = bd_name + "/" + buffer;
48 snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
49 ret_val = bd_name + "/" + buffer;
54 string StoreCache::get_file_name(string device_id_param,
55 Date *date_time_param,
56 EnumSummaryPeriod period_type_param,
57 EnumSummaryCalculationType calc_type_param) {
62 if (period_type_param == PERIOD_YEARLY) {
63 snprintf(buffer, 30, "%d", date_time_param->year);
65 else if (period_type_param == PERIOD_MONTHLY) {
66 snprintf(buffer, 30, "%d-%02d",
67 date_time_param->year,
68 date_time_param->month);
71 snprintf(buffer, 30, "%d-%02d-%02d",
72 date_time_param->year,
73 date_time_param->month,
74 date_time_param->day);
77 fname = fname + DATAFILE_SUFFIX;
78 ret_val = get_dir_name(device_id_param, date_time_param, period_type_param, calc_type_param);
79 ret_val = FileUtil::concat_paths(ret_val, fname);
83 plp::Date *StoreCache::get_scanning_limit_date(EnumSummaryPeriod period_type_param) {
87 cur_data = get_latest_data(date, device_id, period_type_param);
88 if (cur_data != NULL) {
89 ret_val = cur_data->get_date().clone();
90 ret_val->next_second();
95 ret_val = date->clone();
96 if (period_type_param == PERIOD_YEARLY) {
100 ret_val->next_month();
106 DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
113 fname = get_file_name(device_id,
117 if (store_data == NULL) {
118 if (access(fname.c_str(), R_OK) == 0) {
122 if (store_data != NULL) {
123 row_count = store_data->get_count();
125 ret_val = new DataRange();
126 dta = store_data->get(0);
131 if (ret_val == NULL) {
132 switch(period_type_param) {
146 cur_date = date->clone();
147 max_date = get_scanning_limit_date(period_type_param);
152 while(cur_date->before(max_date)) {
153 if (period_type_param == PERIOD_YEARLY) {
154 store = new StoreCache(device_id, cur_date);
155 dr = store->get_mean(PERIOD_MONTHLY);
158 store = new StoreDay(device_id, cur_date);
159 dr = store->get_mean(PERIOD_DAILY);
162 cur_data = dr->get_first();
163 if (cur_data != NULL) {
165 if (res_data == NULL) {
167 val_cnt = res_data->get_value_count();
170 for (ii = 0; ii < val_cnt; ii++) {
171 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
179 if (period_type_param == PERIOD_YEARLY) {
180 cur_date->next_month();
183 cur_date->next_day();
186 if ((res_data != NULL) &&
188 for (ii = 0; ii < val_cnt; ii++) {
189 res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
191 ret_val = new DataRange(res_data);
192 save(fname, ret_val, 4);
201 case PERIOD_MINUTELY:
202 case PERIOD_SECONDLY: {
205 store = new StoreDay(device_id, date);
206 ret_val = store->get_mean(period_type_param);
207 if ((period_type_param != PERIOD_MINUTELY) ||
208 (period_type_param != PERIOD_SECONDLY)) {
209 // no need cache second or minute data
210 save(fname, ret_val, 4);
220 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
228 fname = get_file_name(device_id,
232 if (store_data == NULL) {
233 if (access(fname.c_str(), R_OK) == 0) {
237 if (store_data != NULL) {
238 row_count = store_data->get_count();
240 ret_val = new DataRange();
241 dta = store_data->get(0);
246 if (ret_val == NULL) {
247 switch(period_type_param) {
249 case PERIOD_MONTHLY: {
259 cur_date = date->clone();
260 max_date = get_scanning_limit_date(period_type_param);
264 while(cur_date->before(max_date)) {
265 if (period_type_param == PERIOD_YEARLY) {
266 store = new StoreCache(device_id, cur_date);
267 dr = store->get_sum(PERIOD_MONTHLY);
270 store = new StoreDay(device_id, cur_date);
271 dr = store->get_sum(PERIOD_DAILY);
274 cur_data = dr->get_first();
275 if (cur_data != NULL) {
277 if (res_data == NULL) {
281 val_cnt = res_data->get_value_count();
282 for (ii = 0; ii < val_cnt; ii++) {
283 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
291 if (period_type_param == PERIOD_YEARLY) {
292 cur_date->next_month();
295 cur_date->next_day();
298 if ((res_data != NULL) &&
300 ret_val = new DataRange(res_data);
301 save(fname, ret_val, 4);
310 case PERIOD_MINUTELY:
311 case PERIOD_SECONDLY:
312 store = new StoreDay(device_id, date);
313 ret_val = store->get_sum(period_type_param);
314 if ((period_type_param != PERIOD_MINUTELY) ||
315 (period_type_param != PERIOD_SECONDLY)) {
316 // no need cache second or minute data
317 save(fname, ret_val, 4);
326 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
334 fname = get_file_name(device_id,
338 if (store_data == NULL) {
339 if (access(fname.c_str(), R_OK) == 0) {
340 // read from cache file
344 if (store_data != NULL) {
345 row_count = store_data->get_count();
347 ret_val = new DataRange();
348 dta = store_data->get(0);
353 if (ret_val == NULL) {
354 switch(period_type_param) {
355 case PERIOD_YEARLY: {
361 first_data = get_oldest_data(date, device_id, PERIOD_YEARLY);
362 if (first_data != NULL) {
363 last_data = get_latest_data(date, device_id, PERIOD_YEARLY);
364 if (last_data != NULL) {
365 ret_val = new DataRange();
366 cnt = last_data->get_value_count();
367 for (ii = 0; ii < cnt; ii++) {
368 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
370 ret_val->add(last_data);
374 save(fname, ret_val, 4);
377 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
381 case PERIOD_MONTHLY: {
390 cur_date = date->clone();
391 limit_date = date->clone();
392 limit_date->next_month();
395 while(cur_date->before(limit_date)) {
396 store = new StoreDay(device_id, cur_date);
397 if (first_data == NULL) {
398 cur_data = store->get_oldest_data();
399 if (cur_data != NULL) {
400 first_data = cur_data->clone();
401 last_data = cur_data->clone();
405 cur_data = store->get_latest_data();
406 if (cur_data != NULL) {
407 if (last_data != NULL) {
410 last_data = cur_data;
413 cur_date->next_day();
417 if (first_data != NULL) {
418 if (last_data == NULL) {
419 last_data = first_data->clone();
421 cnt = last_data->get_value_count();
422 for (ii = 0; ii < cnt; ii++) {
423 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
425 cur_date = first_data->get_date().clone();
426 last_data->set_date(cur_date);
428 ret_val = new DataRange(last_data);
431 save(fname, ret_val, 4);
437 case PERIOD_MINUTELY:
438 case PERIOD_SECONDLY:
439 store = new StoreDay(device_id, date);
440 ret_val = store->get_delta(period_type_param);
441 if ((period_type_param != PERIOD_MINUTELY) ||
442 (period_type_param != PERIOD_SECONDLY)) {
443 // no need cache second or minute data
444 save(fname, ret_val, 4);
453 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
461 fname = get_file_name(device_id,
465 if (store_data == NULL) {
466 if (access(fname.c_str(), R_OK) == 0) {
470 if (store_data != NULL) {
471 row_count = store_data->get_count();
473 ret_val = new DataRange();
474 dta = store_data->get(0);
479 if (ret_val == NULL) {
480 switch(period_type_param) {
482 case PERIOD_MONTHLY: {
492 cur_date = date->clone();
493 max_date = get_scanning_limit_date(period_type_param);
497 while(cur_date->before(max_date)) {
498 if (period_type_param == PERIOD_YEARLY) {
499 store = new StoreCache(device_id, cur_date);
500 dr = store->get_max(PERIOD_MONTHLY);
503 store = new StoreDay(device_id, cur_date);
504 dr = store->get_max(PERIOD_DAILY);
507 cur_data = dr->get_first();
508 if (cur_data != NULL) {
510 if (res_data == NULL) {
514 val_cnt = res_data->get_value_count();
516 for (ii = 0; ii < val_cnt; ii++) {
517 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
518 res_data->value_arr[ii] = cur_data->value_arr[ii];
525 new_date = cur_data->get_date();
526 res_data->set_date(&new_date);
534 if (period_type_param == PERIOD_YEARLY) {
535 cur_date->next_month();
538 cur_date->next_day();
541 if ((res_data != NULL) &&
543 ret_val = new DataRange(res_data);
544 save(fname, ret_val, 4);
553 case PERIOD_MINUTELY:
554 case PERIOD_SECONDLY:
555 store = new StoreDay(device_id, date);
556 ret_val = store->get_max(period_type_param);
557 if ((period_type_param != PERIOD_MINUTELY) ||
558 (period_type_param != PERIOD_SECONDLY)) {
559 // no need cache second or minute data
560 save(fname, ret_val, 4);
569 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
577 fname = get_file_name(device_id,
581 if (store_data == NULL) {
582 if (access(fname.c_str(), R_OK) == 0) {
586 if (store_data != NULL) {
587 row_count = store_data->get_count();
589 ret_val = new DataRange();
590 dta = store_data->get(0);
595 if (ret_val == NULL) {
596 switch(period_type_param) {
598 case PERIOD_MONTHLY: {
608 cur_date = date->clone();
609 max_date = get_scanning_limit_date(period_type_param);
613 while(cur_date->before(max_date)) {
614 if (period_type_param == PERIOD_YEARLY) {
615 store = new StoreCache(device_id, cur_date);
616 dr = store->get_min(PERIOD_MONTHLY);
619 store = new StoreDay(device_id, cur_date);
620 dr = store->get_min(PERIOD_DAILY);
623 cur_data = dr->get_first();
624 if (cur_data != NULL) {
626 if (res_data == NULL) {
630 val_cnt = res_data->get_value_count();
632 for (ii = 0; ii < val_cnt; ii++) {
633 if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
634 res_data->value_arr[ii] = cur_data->value_arr[ii];
641 new_date = cur_data->get_date();
642 res_data->set_date(&new_date);
650 if (period_type_param == PERIOD_YEARLY) {
651 cur_date->next_month();
654 cur_date->next_day();
657 if ((res_data != NULL) &&
659 ret_val = new DataRange(res_data);
660 save(fname, ret_val, 4);
669 case PERIOD_MINUTELY:
670 case PERIOD_SECONDLY:
671 store = new StoreDay(device_id, date);
672 ret_val = store->get_min(period_type_param);
673 if ((period_type_param != PERIOD_MINUTELY) ||
674 (period_type_param != PERIOD_SECONDLY)) {
675 // no need cache second or minute data
676 save(fname, ret_val, 4);
685 void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
692 cnt = datarange_param->get_count();
694 //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
695 ostream = FileUtil::open_for_writing(fname_param.c_str());
696 if ((ostream != NULL) &&
697 (ostream->is_open() == true)) {
698 // TODO: add mutex to protect string_list while it's read and emptied
699 for(ii = 0; ii < cnt; ii++) {
700 data = datarange_param->get(ii);
702 line = data->to_string(decimal_count_param);
703 if (line.length() > 0) {
704 *ostream << line << endl;
711 log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
713 if (ostream != NULL) {
719 Data *StoreCache::get_oldest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
724 vector<string> mon_vcr;
725 vector<string> dta_vcr;
734 if (period_type_param == PERIOD_YEARLY) {
735 snprintf(buffer, 30, "%d", date_param->year);
736 year_name.append(buffer);
737 device_dir = DeviceConfig::get_base_dir_name();
738 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
739 year_dr = FileUtil::concat_paths(device_dir, year_name);
740 mon_vcr = FileUtil::get_subdirectories(year_dr);
741 for (ii = 0; ii < mon_vcr.size(); ii++) {
742 mon_dr = mon_vcr.at(ii);
743 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
744 // scan data files from month dir
745 dta_vcr = FileUtil::get_data_files(mon_dr);
746 size = dta_vcr.size();
748 f_name = dta_vcr.at(0);
749 f_name = FileUtil::concat_paths(mon_dr, f_name);
750 store = new StoreDay(f_name);
751 ret_val = store->get_oldest_data();
757 else if (period_type_param == PERIOD_MONTHLY) {
759 snprintf(buffer, 30, "%d", date_param->year);
760 year_name.append(buffer);
761 device_dir = DeviceConfig::get_base_dir_name();
762 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
763 year_dr = FileUtil::concat_paths(device_dir, year_name);
764 snprintf(buffer, 30, "%02d", date_param->month);
765 mon_dr.append(buffer);
766 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
767 // scan data files from month dir
768 dta_vcr = FileUtil::get_data_files(mon_dr);
769 size = dta_vcr.size();
771 f_name = dta_vcr.at(0);
772 f_name = FileUtil::concat_paths(mon_dr, f_name);
773 store = new StoreDay(f_name);
774 ret_val = store->get_oldest_data();
780 store = new StoreDay(device_id_param, date_param);
781 ret_val = store->get_oldest_data();
787 Data *StoreCache::get_latest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
790 vector<string> mon_vcr;
791 vector<string> dta_vcr;
802 if (period_type_param == PERIOD_YEARLY) {
803 snprintf(buffer, 30, "%d", date_param->year);
804 year_name.append(buffer);
805 device_dir = DeviceConfig::get_base_dir_name();
806 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
807 year_dr = FileUtil::concat_paths(device_dir, year_name);
808 mon_vcr = FileUtil::get_subdirectories(year_dr);
809 for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
810 mon_dr = mon_vcr.at(ii);
811 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
812 // scan data files from month dir
813 dta_vcr = FileUtil::get_data_files(mon_dr);
814 size = dta_vcr.size();
816 f_name = dta_vcr.at(size - 1);
817 f_name = FileUtil::concat_paths(mon_dr, f_name);
818 store = new StoreDay(f_name);
819 ret_val = store->get_latest_data();
825 else if (period_type_param == PERIOD_MONTHLY) {
827 snprintf(buffer, 30, "%d", date_param->year);
828 year_name.append(buffer);
829 device_dir = DeviceConfig::get_base_dir_name();
830 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
831 year_dr = FileUtil::concat_paths(device_dir, year_name);
832 snprintf(buffer, 30, "%02d", date_param->month);
833 mon_dr.append(buffer);
834 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
835 // scan data files from month dir
836 dta_vcr = FileUtil::get_data_files(mon_dr);
837 size = dta_vcr.size();
839 f_name = dta_vcr.at(size - 1);
840 f_name = FileUtil::concat_paths(mon_dr, f_name);
841 store = new StoreDay(f_name);
842 ret_val = store->get_latest_data();
848 store = new StoreDay(device_id_param, date_param);
849 ret_val = store->get_latest_data();