4 * Created on: Jan 6, 2011
10 #include "StoreCache.hh"
11 #include "StoreDay.hh"
12 #include "DeviceConfig.hh"
19 StoreCache::StoreCache(string device_id_param,
20 Date *date_time_param): Store(device_id_param, date_time_param) {
23 StoreCache::~StoreCache() {
26 string StoreCache::get_dir_name(string device_id_param,
27 Date *date_time_param,
28 EnumSummaryPeriod period_type_param,
29 EnumSummaryCalculationType calc_type_param) {
34 bd_name = DeviceConfig::get_base_dir_name();
35 bd_name = W1Util::concat_paths(bd_name, CACHE_DIR_NAME);
36 bd_name = W1Util::concat_paths(bd_name, device_id_param);
37 bd_name = W1Util::concat_paths(bd_name, SUMMARY_PERIOD_NAMES_ARRAY[period_type_param]);
38 bd_name = W1Util::concat_paths(bd_name, CALCULATION_TYPE_NAMES_ARRAY[calc_type_param]);
39 if (period_type_param == PERIOD_YEARLY) {
42 else if (period_type_param == PERIOD_MONTHLY) {
43 snprintf(buffer, 30, "%d", date_time_param->year);
44 ret_val = bd_name + "/" + buffer;
47 snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
48 ret_val = bd_name + "/" + buffer;
53 string StoreCache::get_file_name(string device_id_param,
54 Date *date_time_param,
55 EnumSummaryPeriod period_type_param,
56 EnumSummaryCalculationType calc_type_param) {
61 if (period_type_param == PERIOD_YEARLY) {
62 snprintf(buffer, 30, "%d", date_time_param->year);
64 else if (period_type_param == PERIOD_MONTHLY) {
65 snprintf(buffer, 30, "%d-%02d",
66 date_time_param->year,
67 date_time_param->month);
70 snprintf(buffer, 30, "%d-%02d-%02d",
71 date_time_param->year,
72 date_time_param->month,
73 date_time_param->day);
76 fname = fname + DATAFILE_SUFFIX;
77 ret_val = get_dir_name(device_id_param, date_time_param, period_type_param, calc_type_param);
78 ret_val = W1Util::concat_paths(ret_val, fname);
82 plp::Date *StoreCache::get_scanning_limit_date(EnumSummaryPeriod period_type_param) {
86 cur_data = get_newest_data(date, device_id, period_type_param);
87 if (cur_data != NULL) {
88 ret_val = cur_data->get_date().clone();
89 ret_val->next_second();
94 ret_val = date->clone();
95 if (period_type_param == PERIOD_YEARLY) {
99 ret_val->next_month();
105 DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
112 fname = get_file_name(device_id,
116 if (store_data == NULL) {
117 if (access(fname.c_str(), R_OK) == 0) {
121 if (store_data != NULL) {
122 row_count = store_data->get_count();
124 ret_val = new DataRange();
125 dta = store_data->get(0);
130 if (ret_val == NULL) {
131 switch(period_type_param) {
145 cur_date = date->clone();
146 max_date = get_scanning_limit_date(period_type_param);
150 while(cur_date->before(max_date)) {
151 if (period_type_param == PERIOD_YEARLY) {
152 store = new StoreCache(device_id, cur_date);
153 dr = store->get_mean(PERIOD_MONTHLY);
156 store = new StoreDay(device_id, cur_date);
157 dr = store->get_mean(PERIOD_DAILY);
160 cur_data = dr->get_first();
161 if (cur_data != NULL) {
163 if (res_data == NULL) {
165 val_cnt = res_data->get_value_count();
168 for (ii = 0; ii < val_cnt; ii++) {
169 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
177 if (period_type_param == PERIOD_YEARLY) {
178 cur_date->next_month();
181 cur_date->next_day();
184 if ((res_data != NULL) &&
186 for (ii = 0; ii < val_cnt; ii++) {
187 res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
189 ret_val = new DataRange(res_data);
190 save(fname, ret_val, 4);
199 case PERIOD_MINUTELY:
200 case PERIOD_SECONDLY: {
203 store = new StoreDay(device_id, date);
204 ret_val = store->get_mean(period_type_param);
205 if ((period_type_param != PERIOD_MINUTELY) ||
206 (period_type_param != PERIOD_SECONDLY)) {
207 // no need cache second or minute data
208 save(fname, ret_val, 4);
218 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
226 fname = get_file_name(device_id,
230 if (store_data == NULL) {
231 if (access(fname.c_str(), R_OK) == 0) {
235 if (store_data != NULL) {
236 row_count = store_data->get_count();
238 ret_val = new DataRange();
239 dta = store_data->get(0);
244 if (ret_val == NULL) {
245 switch(period_type_param) {
247 case PERIOD_MONTHLY: {
257 cur_date = date->clone();
258 max_date = get_scanning_limit_date(period_type_param);
262 while(cur_date->before(max_date)) {
263 if (period_type_param == PERIOD_YEARLY) {
264 store = new StoreCache(device_id, cur_date);
265 dr = store->get_sum(PERIOD_MONTHLY);
268 store = new StoreDay(device_id, cur_date);
269 dr = store->get_sum(PERIOD_DAILY);
272 cur_data = dr->get_first();
273 if (cur_data != NULL) {
275 if (res_data == NULL) {
279 val_cnt = res_data->get_value_count();
280 for (ii = 0; ii < val_cnt; ii++) {
281 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
289 if (period_type_param == PERIOD_YEARLY) {
290 cur_date->next_month();
293 cur_date->next_day();
296 if ((res_data != NULL) &&
298 ret_val = new DataRange(res_data);
299 save(fname, ret_val, 4);
308 case PERIOD_MINUTELY:
309 case PERIOD_SECONDLY:
310 store = new StoreDay(device_id, date);
311 ret_val = store->get_sum(period_type_param);
312 if ((period_type_param != PERIOD_MINUTELY) ||
313 (period_type_param != PERIOD_SECONDLY)) {
314 // no need cache second or minute data
315 save(fname, ret_val, 4);
324 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
332 fname = get_file_name(device_id,
336 if (store_data == NULL) {
337 if (access(fname.c_str(), R_OK) == 0) {
338 // read from cache file
342 if (store_data != NULL) {
343 row_count = store_data->get_count();
345 ret_val = new DataRange();
346 dta = store_data->get(0);
351 if (ret_val == NULL) {
352 switch(period_type_param) {
353 case PERIOD_YEARLY: {
359 first_data = get_oldest_data(date, device_id, PERIOD_YEARLY);
360 if (first_data != NULL) {
361 last_data = get_newest_data(date, device_id, PERIOD_YEARLY);
362 if (last_data != NULL) {
363 ret_val = new DataRange();
364 cnt = last_data->get_value_count();
365 for (ii = 0; ii < cnt; ii++) {
366 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
368 ret_val->add(last_data);
372 save(fname, ret_val, 4);
375 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
379 case PERIOD_MONTHLY: {
388 cur_date = date->clone();
389 limit_date = date->clone();
390 limit_date->next_month();
393 while(cur_date->before(limit_date)) {
394 store = new StoreDay(device_id, cur_date);
395 if (first_data == NULL) {
396 cur_data = store->get_oldest_data();
397 if (cur_data != NULL) {
398 first_data = cur_data->clone();
399 last_data = cur_data->clone();
403 cur_data = store->get_newest_data();
404 if (cur_data != NULL) {
405 if (last_data != NULL) {
408 last_data = cur_data;
411 cur_date->next_day();
415 if (first_data != NULL) {
416 if (last_data == NULL) {
417 last_data = first_data->clone();
419 cnt = last_data->get_value_count();
420 for (ii = 0; ii < cnt; ii++) {
421 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
423 cur_date = first_data->get_date().clone();
424 last_data->set_date(cur_date);
426 ret_val = new DataRange(last_data);
429 save(fname, ret_val, 4);
435 case PERIOD_MINUTELY:
436 case PERIOD_SECONDLY:
437 store = new StoreDay(device_id, date);
438 ret_val = store->get_delta(period_type_param);
439 if ((period_type_param != PERIOD_MINUTELY) ||
440 (period_type_param != PERIOD_SECONDLY)) {
441 // no need cache second or minute data
442 save(fname, ret_val, 4);
451 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
459 fname = get_file_name(device_id,
463 if (store_data == NULL) {
464 if (access(fname.c_str(), R_OK) == 0) {
468 if (store_data != NULL) {
469 row_count = store_data->get_count();
471 ret_val = new DataRange();
472 dta = store_data->get(0);
477 if (ret_val == NULL) {
478 switch(period_type_param) {
480 case PERIOD_MONTHLY: {
490 cur_date = date->clone();
491 max_date = get_scanning_limit_date(period_type_param);
495 while(cur_date->before(max_date)) {
496 if (period_type_param == PERIOD_YEARLY) {
497 store = new StoreCache(device_id, cur_date);
498 dr = store->get_max(PERIOD_MONTHLY);
501 store = new StoreDay(device_id, cur_date);
502 dr = store->get_max(PERIOD_DAILY);
505 cur_data = dr->get_first();
506 if (cur_data != NULL) {
508 if (res_data == NULL) {
512 val_cnt = res_data->get_value_count();
514 for (ii = 0; ii < val_cnt; ii++) {
515 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
516 res_data->value_arr[ii] = cur_data->value_arr[ii];
523 new_date = cur_data->get_date();
524 res_data->set_date(&new_date);
532 if (period_type_param == PERIOD_YEARLY) {
533 cur_date->next_month();
536 cur_date->next_day();
539 if ((res_data != NULL) &&
541 ret_val = new DataRange(res_data);
542 save(fname, ret_val, 4);
551 case PERIOD_MINUTELY:
552 case PERIOD_SECONDLY:
553 store = new StoreDay(device_id, date);
554 ret_val = store->get_max(period_type_param);
555 if ((period_type_param != PERIOD_MINUTELY) ||
556 (period_type_param != PERIOD_SECONDLY)) {
557 // no need cache second or minute data
558 save(fname, ret_val, 4);
567 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
575 fname = get_file_name(device_id,
579 if (store_data == NULL) {
580 if (access(fname.c_str(), R_OK) == 0) {
584 if (store_data != NULL) {
585 row_count = store_data->get_count();
587 ret_val = new DataRange();
588 dta = store_data->get(0);
593 if (ret_val == NULL) {
594 switch(period_type_param) {
596 case PERIOD_MONTHLY: {
606 cur_date = date->clone();
607 max_date = get_scanning_limit_date(period_type_param);
611 while(cur_date->before(max_date)) {
612 if (period_type_param == PERIOD_YEARLY) {
613 store = new StoreCache(device_id, cur_date);
614 dr = store->get_min(PERIOD_MONTHLY);
617 store = new StoreDay(device_id, cur_date);
618 dr = store->get_min(PERIOD_DAILY);
621 cur_data = dr->get_first();
622 if (cur_data != NULL) {
624 if (res_data == NULL) {
628 val_cnt = res_data->get_value_count();
630 for (ii = 0; ii < val_cnt; ii++) {
631 if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
632 res_data->value_arr[ii] = cur_data->value_arr[ii];
639 new_date = cur_data->get_date();
640 res_data->set_date(&new_date);
648 if (period_type_param == PERIOD_YEARLY) {
649 cur_date->next_month();
652 cur_date->next_day();
655 if ((res_data != NULL) &&
657 ret_val = new DataRange(res_data);
658 save(fname, ret_val, 4);
667 case PERIOD_MINUTELY:
668 case PERIOD_SECONDLY:
669 store = new StoreDay(device_id, date);
670 ret_val = store->get_min(period_type_param);
671 if ((period_type_param != PERIOD_MINUTELY) ||
672 (period_type_param != PERIOD_SECONDLY)) {
673 // no need cache second or minute data
674 save(fname, ret_val, 4);
683 void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
690 cnt = datarange_param->get_count();
692 //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
693 ostream = W1Util::open_for_writing(fname_param.c_str());
694 if ((ostream != NULL) &&
695 (ostream->is_open() == true)) {
696 // TODO: add mutex to protect string_list while it's read and emptied
697 for(ii = 0; ii < cnt; ii++) {
698 data = datarange_param->get(ii);
700 line = data->to_string(decimal_count_param);
701 if (line.length() > 0) {
702 *ostream << line << endl;
709 log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
711 if (ostream != NULL) {
717 Data *StoreCache::get_oldest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
722 vector<string> mon_vcr;
723 vector<string> dta_vcr;
732 if (period_type_param == PERIOD_YEARLY) {
733 snprintf(buffer, 30, "%d", date_param->year);
734 year_name.append(buffer);
735 device_dir = DeviceConfig::get_base_dir_name();
736 device_dir = W1Util::concat_paths(device_dir, device_id_param);
737 year_dr = W1Util::concat_paths(device_dir, year_name);
738 mon_vcr = W1Util::get_subdirectories(year_dr);
739 for (ii = 0; ii < mon_vcr.size(); ii++) {
740 mon_dr = mon_vcr.at(ii);
741 mon_dr = W1Util::concat_paths(year_dr, mon_dr);
742 // scan data files from month dir
743 dta_vcr = W1Util::get_data_files(mon_dr);
744 size = dta_vcr.size();
746 f_name = dta_vcr.at(0);
747 f_name = W1Util::concat_paths(mon_dr, f_name);
748 store = new StoreDay(f_name);
749 ret_val = store->get_oldest_data();
755 else if (period_type_param == PERIOD_MONTHLY) {
757 snprintf(buffer, 30, "%d", date_param->year);
758 year_name.append(buffer);
759 device_dir = DeviceConfig::get_base_dir_name();
760 device_dir = W1Util::concat_paths(device_dir, device_id_param);
761 year_dr = W1Util::concat_paths(device_dir, year_name);
762 snprintf(buffer, 30, "%02d", date_param->month);
763 mon_dr.append(buffer);
764 mon_dr = W1Util::concat_paths(year_dr, mon_dr);
765 // scan data files from month dir
766 dta_vcr = W1Util::get_data_files(mon_dr);
767 size = dta_vcr.size();
769 f_name = dta_vcr.at(0);
770 f_name = W1Util::concat_paths(mon_dr, f_name);
771 store = new StoreDay(f_name);
772 ret_val = store->get_oldest_data();
778 store = new StoreDay(device_id_param, date_param);
779 ret_val = store->get_oldest_data();
785 Data *StoreCache::get_newest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
788 vector<string> mon_vcr;
789 vector<string> dta_vcr;
800 if (period_type_param == PERIOD_YEARLY) {
801 snprintf(buffer, 30, "%d", date_param->year);
802 year_name.append(buffer);
803 device_dir = DeviceConfig::get_base_dir_name();
804 device_dir = W1Util::concat_paths(device_dir, device_id_param);
805 year_dr = W1Util::concat_paths(device_dir, year_name);
806 mon_vcr = W1Util::get_subdirectories(year_dr);
807 for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
808 mon_dr = mon_vcr.at(ii);
809 mon_dr = W1Util::concat_paths(year_dr, mon_dr);
810 // scan data files from month dir
811 dta_vcr = W1Util::get_data_files(mon_dr);
812 size = dta_vcr.size();
814 f_name = dta_vcr.at(size - 1);
815 f_name = W1Util::concat_paths(mon_dr, f_name);
816 store = new StoreDay(f_name);
817 ret_val = store->get_newest_data();
823 else if (period_type_param == PERIOD_MONTHLY) {
825 snprintf(buffer, 30, "%d", date_param->year);
826 year_name.append(buffer);
827 device_dir = DeviceConfig::get_base_dir_name();
828 device_dir = W1Util::concat_paths(device_dir, device_id_param);
829 year_dr = W1Util::concat_paths(device_dir, year_name);
830 snprintf(buffer, 30, "%02d", date_param->month);
831 mon_dr.append(buffer);
832 mon_dr = W1Util::concat_paths(year_dr, mon_dr);
833 // scan data files from month dir
834 dta_vcr = W1Util::get_data_files(mon_dr);
835 size = dta_vcr.size();
837 f_name = dta_vcr.at(size - 1);
838 f_name = W1Util::concat_paths(mon_dr, f_name);
839 store = new StoreDay(f_name);
840 ret_val = store->get_newest_data();
846 store = new StoreDay(device_id_param, date_param);
847 ret_val = store->get_newest_data();