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);
151 while(cur_date->before(max_date)) {
152 if (period_type_param == PERIOD_YEARLY) {
153 store = new StoreCache(device_id, cur_date);
154 dr = store->get_mean(PERIOD_MONTHLY);
157 store = new StoreDay(device_id, cur_date);
158 dr = store->get_mean(PERIOD_DAILY);
161 cur_data = dr->get_first();
162 if (cur_data != NULL) {
164 if (res_data == NULL) {
166 val_cnt = res_data->get_value_count();
169 for (ii = 0; ii < val_cnt; ii++) {
170 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
178 if (period_type_param == PERIOD_YEARLY) {
179 cur_date->next_month();
182 cur_date->next_day();
185 if ((res_data != NULL) &&
187 for (ii = 0; ii < val_cnt; ii++) {
188 res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
190 ret_val = new DataRange(res_data);
191 save(fname, ret_val, 4);
200 case PERIOD_MINUTELY:
201 case PERIOD_SECONDLY: {
204 store = new StoreDay(device_id, date);
205 ret_val = store->get_mean(period_type_param);
206 if ((period_type_param != PERIOD_MINUTELY) ||
207 (period_type_param != PERIOD_SECONDLY)) {
208 // no need cache second or minute data
209 save(fname, ret_val, 4);
219 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
227 fname = get_file_name(device_id,
231 if (store_data == NULL) {
232 if (access(fname.c_str(), R_OK) == 0) {
236 if (store_data != NULL) {
237 row_count = store_data->get_count();
239 ret_val = new DataRange();
240 dta = store_data->get(0);
245 if (ret_val == NULL) {
246 switch(period_type_param) {
248 case PERIOD_MONTHLY: {
258 cur_date = date->clone();
259 max_date = get_scanning_limit_date(period_type_param);
263 while(cur_date->before(max_date)) {
264 if (period_type_param == PERIOD_YEARLY) {
265 store = new StoreCache(device_id, cur_date);
266 dr = store->get_sum(PERIOD_MONTHLY);
269 store = new StoreDay(device_id, cur_date);
270 dr = store->get_sum(PERIOD_DAILY);
273 cur_data = dr->get_first();
274 if (cur_data != NULL) {
276 if (res_data == NULL) {
280 val_cnt = res_data->get_value_count();
281 for (ii = 0; ii < val_cnt; ii++) {
282 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
290 if (period_type_param == PERIOD_YEARLY) {
291 cur_date->next_month();
294 cur_date->next_day();
297 if ((res_data != NULL) &&
299 ret_val = new DataRange(res_data);
300 save(fname, ret_val, 4);
309 case PERIOD_MINUTELY:
310 case PERIOD_SECONDLY:
311 store = new StoreDay(device_id, date);
312 ret_val = store->get_sum(period_type_param);
313 if ((period_type_param != PERIOD_MINUTELY) ||
314 (period_type_param != PERIOD_SECONDLY)) {
315 // no need cache second or minute data
316 save(fname, ret_val, 4);
325 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
333 fname = get_file_name(device_id,
337 if (store_data == NULL) {
338 if (access(fname.c_str(), R_OK) == 0) {
339 // read from cache file
343 if (store_data != NULL) {
344 row_count = store_data->get_count();
346 ret_val = new DataRange();
347 dta = store_data->get(0);
352 if (ret_val == NULL) {
353 switch(period_type_param) {
354 case PERIOD_YEARLY: {
360 first_data = get_oldest_data(date, device_id, PERIOD_YEARLY);
361 if (first_data != NULL) {
362 last_data = get_latest_data(date, device_id, PERIOD_YEARLY);
363 if (last_data != NULL) {
364 ret_val = new DataRange();
365 cnt = last_data->get_value_count();
366 for (ii = 0; ii < cnt; ii++) {
367 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
369 ret_val->add(last_data);
373 save(fname, ret_val, 4);
376 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
380 case PERIOD_MONTHLY: {
389 cur_date = date->clone();
390 limit_date = date->clone();
391 limit_date->next_month();
394 while(cur_date->before(limit_date)) {
395 store = new StoreDay(device_id, cur_date);
396 if (first_data == NULL) {
397 cur_data = store->get_oldest_data();
398 if (cur_data != NULL) {
399 first_data = cur_data->clone();
400 last_data = cur_data->clone();
404 cur_data = store->get_latest_data();
405 if (cur_data != NULL) {
406 if (last_data != NULL) {
409 last_data = cur_data;
412 cur_date->next_day();
416 if (first_data != NULL) {
417 if (last_data == NULL) {
418 last_data = first_data->clone();
420 cnt = last_data->get_value_count();
421 for (ii = 0; ii < cnt; ii++) {
422 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
424 cur_date = first_data->get_date().clone();
425 last_data->set_date(cur_date);
427 ret_val = new DataRange(last_data);
430 save(fname, ret_val, 4);
436 case PERIOD_MINUTELY:
437 case PERIOD_SECONDLY:
438 store = new StoreDay(device_id, date);
439 ret_val = store->get_delta(period_type_param);
440 if ((period_type_param != PERIOD_MINUTELY) ||
441 (period_type_param != PERIOD_SECONDLY)) {
442 // no need cache second or minute data
443 save(fname, ret_val, 4);
452 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
460 fname = get_file_name(device_id,
464 if (store_data == NULL) {
465 if (access(fname.c_str(), R_OK) == 0) {
469 if (store_data != NULL) {
470 row_count = store_data->get_count();
472 ret_val = new DataRange();
473 dta = store_data->get(0);
478 if (ret_val == NULL) {
479 switch(period_type_param) {
481 case PERIOD_MONTHLY: {
491 cur_date = date->clone();
492 max_date = get_scanning_limit_date(period_type_param);
496 while(cur_date->before(max_date)) {
497 if (period_type_param == PERIOD_YEARLY) {
498 store = new StoreCache(device_id, cur_date);
499 dr = store->get_max(PERIOD_MONTHLY);
502 store = new StoreDay(device_id, cur_date);
503 dr = store->get_max(PERIOD_DAILY);
506 cur_data = dr->get_first();
507 if (cur_data != NULL) {
509 if (res_data == NULL) {
513 val_cnt = res_data->get_value_count();
515 for (ii = 0; ii < val_cnt; ii++) {
516 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
517 res_data->value_arr[ii] = cur_data->value_arr[ii];
524 new_date = cur_data->get_date();
525 res_data->set_date(&new_date);
533 if (period_type_param == PERIOD_YEARLY) {
534 cur_date->next_month();
537 cur_date->next_day();
540 if ((res_data != NULL) &&
542 ret_val = new DataRange(res_data);
543 save(fname, ret_val, 4);
552 case PERIOD_MINUTELY:
553 case PERIOD_SECONDLY:
554 store = new StoreDay(device_id, date);
555 ret_val = store->get_max(period_type_param);
556 if ((period_type_param != PERIOD_MINUTELY) ||
557 (period_type_param != PERIOD_SECONDLY)) {
558 // no need cache second or minute data
559 save(fname, ret_val, 4);
568 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
576 fname = get_file_name(device_id,
580 if (store_data == NULL) {
581 if (access(fname.c_str(), R_OK) == 0) {
585 if (store_data != NULL) {
586 row_count = store_data->get_count();
588 ret_val = new DataRange();
589 dta = store_data->get(0);
594 if (ret_val == NULL) {
595 switch(period_type_param) {
597 case PERIOD_MONTHLY: {
607 cur_date = date->clone();
608 max_date = get_scanning_limit_date(period_type_param);
612 while(cur_date->before(max_date)) {
613 if (period_type_param == PERIOD_YEARLY) {
614 store = new StoreCache(device_id, cur_date);
615 dr = store->get_min(PERIOD_MONTHLY);
618 store = new StoreDay(device_id, cur_date);
619 dr = store->get_min(PERIOD_DAILY);
622 cur_data = dr->get_first();
623 if (cur_data != NULL) {
625 if (res_data == NULL) {
629 val_cnt = res_data->get_value_count();
631 for (ii = 0; ii < val_cnt; ii++) {
632 if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
633 res_data->value_arr[ii] = cur_data->value_arr[ii];
640 new_date = cur_data->get_date();
641 res_data->set_date(&new_date);
649 if (period_type_param == PERIOD_YEARLY) {
650 cur_date->next_month();
653 cur_date->next_day();
656 if ((res_data != NULL) &&
658 ret_val = new DataRange(res_data);
659 save(fname, ret_val, 4);
668 case PERIOD_MINUTELY:
669 case PERIOD_SECONDLY:
670 store = new StoreDay(device_id, date);
671 ret_val = store->get_min(period_type_param);
672 if ((period_type_param != PERIOD_MINUTELY) ||
673 (period_type_param != PERIOD_SECONDLY)) {
674 // no need cache second or minute data
675 save(fname, ret_val, 4);
684 void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
691 cnt = datarange_param->get_count();
693 //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
694 ostream = FileUtil::open_for_writing(fname_param.c_str());
695 if ((ostream != NULL) &&
696 (ostream->is_open() == true)) {
697 // TODO: add mutex to protect string_list while it's read and emptied
698 for(ii = 0; ii < cnt; ii++) {
699 data = datarange_param->get(ii);
701 line = data->to_string(decimal_count_param);
702 if (line.length() > 0) {
703 *ostream << line << endl;
710 log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
712 if (ostream != NULL) {
718 Data *StoreCache::get_oldest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
723 vector<string> mon_vcr;
724 vector<string> dta_vcr;
733 if (period_type_param == PERIOD_YEARLY) {
734 snprintf(buffer, 30, "%d", date_param->year);
735 year_name.append(buffer);
736 device_dir = DeviceConfig::get_base_dir_name();
737 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
738 year_dr = FileUtil::concat_paths(device_dir, year_name);
739 mon_vcr = FileUtil::get_subdirectories(year_dr);
740 for (ii = 0; ii < mon_vcr.size(); ii++) {
741 mon_dr = mon_vcr.at(ii);
742 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
743 // scan data files from month dir
744 dta_vcr = FileUtil::get_data_files(mon_dr);
745 size = dta_vcr.size();
747 f_name = dta_vcr.at(0);
748 f_name = FileUtil::concat_paths(mon_dr, f_name);
749 store = new StoreDay(f_name);
750 ret_val = store->get_oldest_data();
756 else if (period_type_param == PERIOD_MONTHLY) {
758 snprintf(buffer, 30, "%d", date_param->year);
759 year_name.append(buffer);
760 device_dir = DeviceConfig::get_base_dir_name();
761 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
762 year_dr = FileUtil::concat_paths(device_dir, year_name);
763 snprintf(buffer, 30, "%02d", date_param->month);
764 mon_dr.append(buffer);
765 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
766 // scan data files from month dir
767 dta_vcr = FileUtil::get_data_files(mon_dr);
768 size = dta_vcr.size();
770 f_name = dta_vcr.at(0);
771 f_name = FileUtil::concat_paths(mon_dr, f_name);
772 store = new StoreDay(f_name);
773 ret_val = store->get_oldest_data();
779 store = new StoreDay(device_id_param, date_param);
780 ret_val = store->get_oldest_data();
786 Data *StoreCache::get_latest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
789 vector<string> mon_vcr;
790 vector<string> dta_vcr;
801 if (period_type_param == PERIOD_YEARLY) {
802 snprintf(buffer, 30, "%d", date_param->year);
803 year_name.append(buffer);
804 device_dir = DeviceConfig::get_base_dir_name();
805 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
806 year_dr = FileUtil::concat_paths(device_dir, year_name);
807 mon_vcr = FileUtil::get_subdirectories(year_dr);
808 for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
809 mon_dr = mon_vcr.at(ii);
810 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
811 // scan data files from month dir
812 dta_vcr = FileUtil::get_data_files(mon_dr);
813 size = dta_vcr.size();
815 f_name = dta_vcr.at(size - 1);
816 f_name = FileUtil::concat_paths(mon_dr, f_name);
817 store = new StoreDay(f_name);
818 ret_val = store->get_latest_data();
824 else if (period_type_param == PERIOD_MONTHLY) {
826 snprintf(buffer, 30, "%d", date_param->year);
827 year_name.append(buffer);
828 device_dir = DeviceConfig::get_base_dir_name();
829 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
830 year_dr = FileUtil::concat_paths(device_dir, year_name);
831 snprintf(buffer, 30, "%02d", date_param->month);
832 mon_dr.append(buffer);
833 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
834 // scan data files from month dir
835 dta_vcr = FileUtil::get_data_files(mon_dr);
836 size = dta_vcr.size();
838 f_name = dta_vcr.at(size - 1);
839 f_name = FileUtil::concat_paths(mon_dr, f_name);
840 store = new StoreDay(f_name);
841 ret_val = store->get_latest_data();
847 store = new StoreDay(device_id_param, date_param);
848 ret_val = store->get_latest_data();