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) {
37 period_name = DataSummary::get_summary_period_name(period_type_param);
38 calc_type = DataSummary::get_summary_calculation_name(calc_type_param);
40 bd_name = DeviceConfig::get_base_dir_name();
41 bd_name = FileUtil::concat_paths(bd_name, CACHE_DIR_NAME);
42 bd_name = FileUtil::concat_paths(bd_name, device_id_param);
43 bd_name = FileUtil::concat_paths(bd_name, period_name);
44 bd_name = FileUtil::concat_paths(bd_name, calc_type);
45 if (period_type_param == PERIOD_YEARLY) {
48 else if (period_type_param == PERIOD_MONTHLY) {
49 snprintf(buffer, 30, "%d", date_time_param->year);
50 ret_val = bd_name + "/" + buffer;
53 snprintf(buffer, 30, "%d/%02d", date_time_param->year, date_time_param->month);
54 ret_val = bd_name + "/" + buffer;
59 string StoreCache::get_file_name(string device_id_param,
60 Date *date_time_param,
61 EnumSummaryPeriod period_type_param,
62 EnumSummaryCalculationType calc_type_param) {
67 if (period_type_param == PERIOD_YEARLY) {
68 snprintf(buffer, 30, "%d", date_time_param->year);
70 else if (period_type_param == PERIOD_MONTHLY) {
71 snprintf(buffer, 30, "%d-%02d",
72 date_time_param->year,
73 date_time_param->month);
76 snprintf(buffer, 30, "%d-%02d-%02d",
77 date_time_param->year,
78 date_time_param->month,
79 date_time_param->day);
82 fname = fname + DATAFILE_SUFFIX;
83 ret_val = get_dir_name(device_id_param, date_time_param, period_type_param, calc_type_param);
84 ret_val = FileUtil::concat_paths(ret_val, fname);
88 plp::Date *StoreCache::get_scanning_limit_date(EnumSummaryPeriod period_type_param) {
92 cur_data = get_latest_data(date, device_id, period_type_param);
93 if (cur_data != NULL) {
94 ret_val = cur_data->get_date().clone();
95 ret_val->next_second();
100 ret_val = date->clone();
101 if (period_type_param == PERIOD_YEARLY) {
102 ret_val->next_year();
105 ret_val->next_month();
111 DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
118 fname = get_file_name(device_id,
122 if (store_data == NULL) {
123 if (access(fname.c_str(), R_OK) == 0) {
127 if (store_data != NULL) {
128 row_count = store_data->get_count();
130 ret_val = new DataRange();
131 dta = store_data->get(0);
136 if (ret_val == NULL) {
137 switch(period_type_param) {
151 cur_date = date->clone();
152 max_date = get_scanning_limit_date(period_type_param);
157 while(cur_date->before(max_date)) {
158 if (period_type_param == PERIOD_YEARLY) {
159 store = new StoreCache(device_id, cur_date);
160 dr = store->get_mean(PERIOD_MONTHLY);
163 store = new StoreDay(device_id, cur_date);
164 dr = store->get_mean(PERIOD_DAILY);
167 cur_data = dr->get_first();
168 if (cur_data != NULL) {
170 if (res_data == NULL) {
172 val_cnt = res_data->get_value_count();
175 for (ii = 0; ii < val_cnt; ii++) {
176 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
184 if (period_type_param == PERIOD_YEARLY) {
185 cur_date->next_month();
188 cur_date->next_day();
191 if ((res_data != NULL) &&
193 for (ii = 0; ii < val_cnt; ii++) {
194 res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
196 ret_val = new DataRange(res_data);
197 save(fname, ret_val, 4);
206 case PERIOD_MINUTELY:
207 case PERIOD_SECONDLY: {
210 store = new StoreDay(device_id, date);
211 ret_val = store->get_mean(period_type_param);
212 if ((period_type_param != PERIOD_MINUTELY) ||
213 (period_type_param != PERIOD_SECONDLY)) {
214 // no need cache second or minute data
215 save(fname, ret_val, 4);
225 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
233 fname = get_file_name(device_id,
237 if (store_data == NULL) {
238 if (access(fname.c_str(), R_OK) == 0) {
242 if (store_data != NULL) {
243 row_count = store_data->get_count();
245 ret_val = new DataRange();
246 dta = store_data->get(0);
251 if (ret_val == NULL) {
252 switch(period_type_param) {
254 case PERIOD_MONTHLY: {
264 cur_date = date->clone();
265 max_date = get_scanning_limit_date(period_type_param);
269 while(cur_date->before(max_date)) {
270 if (period_type_param == PERIOD_YEARLY) {
271 store = new StoreCache(device_id, cur_date);
272 dr = store->get_sum(PERIOD_MONTHLY);
275 store = new StoreDay(device_id, cur_date);
276 dr = store->get_sum(PERIOD_DAILY);
279 cur_data = dr->get_first();
280 if (cur_data != NULL) {
282 if (res_data == NULL) {
286 val_cnt = res_data->get_value_count();
287 for (ii = 0; ii < val_cnt; ii++) {
288 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
296 if (period_type_param == PERIOD_YEARLY) {
297 cur_date->next_month();
300 cur_date->next_day();
303 if ((res_data != NULL) &&
305 ret_val = new DataRange(res_data);
306 save(fname, ret_val, 4);
315 case PERIOD_MINUTELY:
316 case PERIOD_SECONDLY:
317 store = new StoreDay(device_id, date);
318 ret_val = store->get_sum(period_type_param);
319 if ((period_type_param != PERIOD_MINUTELY) ||
320 (period_type_param != PERIOD_SECONDLY)) {
321 // no need cache second or minute data
322 save(fname, ret_val, 4);
331 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
339 fname = get_file_name(device_id,
343 if (store_data == NULL) {
344 if (access(fname.c_str(), R_OK) == 0) {
345 // read from cache file
349 if (store_data != NULL) {
350 row_count = store_data->get_count();
352 ret_val = new DataRange();
353 dta = store_data->get(0);
358 if (ret_val == NULL) {
359 switch(period_type_param) {
360 case PERIOD_YEARLY: {
366 first_data = get_oldest_data(date, device_id, PERIOD_YEARLY);
367 if (first_data != NULL) {
368 last_data = get_latest_data(date, device_id, PERIOD_YEARLY);
369 if (last_data != NULL) {
370 ret_val = new DataRange();
371 cnt = last_data->get_value_count();
372 for (ii = 0; ii < cnt; ii++) {
373 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
375 ret_val->add(last_data);
379 save(fname, ret_val, 4);
382 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
386 case PERIOD_MONTHLY: {
395 cur_date = date->clone();
396 limit_date = date->clone();
397 limit_date->next_month();
400 while(cur_date->before(limit_date)) {
401 store = new StoreDay(device_id, cur_date);
402 if (first_data == NULL) {
403 cur_data = store->get_oldest_data();
404 if (cur_data != NULL) {
405 first_data = cur_data->clone();
406 last_data = cur_data->clone();
410 cur_data = store->get_latest_data();
411 if (cur_data != NULL) {
412 if (last_data != NULL) {
415 last_data = cur_data;
418 cur_date->next_day();
422 if (first_data != NULL) {
423 if (last_data == NULL) {
424 last_data = first_data->clone();
426 cnt = last_data->get_value_count();
427 for (ii = 0; ii < cnt; ii++) {
428 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
430 cur_date = first_data->get_date().clone();
431 last_data->set_date(cur_date);
433 ret_val = new DataRange(last_data);
436 save(fname, ret_val, 4);
442 case PERIOD_MINUTELY:
443 case PERIOD_SECONDLY:
444 store = new StoreDay(device_id, date);
445 ret_val = store->get_delta(period_type_param);
446 if ((period_type_param != PERIOD_MINUTELY) ||
447 (period_type_param != PERIOD_SECONDLY)) {
448 // no need cache second or minute data
449 save(fname, ret_val, 4);
458 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
466 fname = get_file_name(device_id,
470 if (store_data == NULL) {
471 if (access(fname.c_str(), R_OK) == 0) {
475 if (store_data != NULL) {
476 row_count = store_data->get_count();
478 ret_val = new DataRange();
479 dta = store_data->get(0);
484 if (ret_val == NULL) {
485 switch(period_type_param) {
487 case PERIOD_MONTHLY: {
497 cur_date = date->clone();
498 max_date = get_scanning_limit_date(period_type_param);
502 while(cur_date->before(max_date)) {
503 if (period_type_param == PERIOD_YEARLY) {
504 store = new StoreCache(device_id, cur_date);
505 dr = store->get_max(PERIOD_MONTHLY);
508 store = new StoreDay(device_id, cur_date);
509 dr = store->get_max(PERIOD_DAILY);
512 cur_data = dr->get_first();
513 if (cur_data != NULL) {
515 if (res_data == NULL) {
519 val_cnt = res_data->get_value_count();
521 for (ii = 0; ii < val_cnt; ii++) {
522 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
523 res_data->value_arr[ii] = cur_data->value_arr[ii];
530 new_date = cur_data->get_date();
531 res_data->set_date(&new_date);
539 if (period_type_param == PERIOD_YEARLY) {
540 cur_date->next_month();
543 cur_date->next_day();
546 if ((res_data != NULL) &&
548 ret_val = new DataRange(res_data);
549 save(fname, ret_val, 4);
558 case PERIOD_MINUTELY:
559 case PERIOD_SECONDLY:
560 store = new StoreDay(device_id, date);
561 ret_val = store->get_max(period_type_param);
562 if ((period_type_param != PERIOD_MINUTELY) ||
563 (period_type_param != PERIOD_SECONDLY)) {
564 // no need cache second or minute data
565 save(fname, ret_val, 4);
574 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
582 fname = get_file_name(device_id,
586 if (store_data == NULL) {
587 if (access(fname.c_str(), R_OK) == 0) {
591 if (store_data != NULL) {
592 row_count = store_data->get_count();
594 ret_val = new DataRange();
595 dta = store_data->get(0);
600 if (ret_val == NULL) {
601 switch(period_type_param) {
603 case PERIOD_MONTHLY: {
613 cur_date = date->clone();
614 max_date = get_scanning_limit_date(period_type_param);
618 while(cur_date->before(max_date)) {
619 if (period_type_param == PERIOD_YEARLY) {
620 store = new StoreCache(device_id, cur_date);
621 dr = store->get_min(PERIOD_MONTHLY);
624 store = new StoreDay(device_id, cur_date);
625 dr = store->get_min(PERIOD_DAILY);
628 cur_data = dr->get_first();
629 if (cur_data != NULL) {
631 if (res_data == NULL) {
635 val_cnt = res_data->get_value_count();
637 for (ii = 0; ii < val_cnt; ii++) {
638 if (cur_data->value_arr[ii] < res_data->value_arr[ii]) {
639 res_data->value_arr[ii] = cur_data->value_arr[ii];
646 new_date = cur_data->get_date();
647 res_data->set_date(&new_date);
655 if (period_type_param == PERIOD_YEARLY) {
656 cur_date->next_month();
659 cur_date->next_day();
662 if ((res_data != NULL) &&
664 ret_val = new DataRange(res_data);
665 save(fname, ret_val, 4);
674 case PERIOD_MINUTELY:
675 case PERIOD_SECONDLY:
676 store = new StoreDay(device_id, date);
677 ret_val = store->get_min(period_type_param);
678 if ((period_type_param != PERIOD_MINUTELY) ||
679 (period_type_param != PERIOD_SECONDLY)) {
680 // no need cache second or minute data
681 save(fname, ret_val, 4);
690 void StoreCache::save(std::string fname_param, plp::DataRange *datarange_param, int decimal_count_param) {
697 cnt = datarange_param->get_count();
699 //log_info("[%s] cacheing %d data values.\n", device_id.c_str(), cnt);
700 ostream = FileUtil::open_for_writing(fname_param.c_str());
701 if ((ostream != NULL) &&
702 (ostream->is_open() == true)) {
703 // TODO: add mutex to protect string_list while it's read and emptied
704 for(ii = 0; ii < cnt; ii++) {
705 data = datarange_param->get(ii);
707 line = data->to_string(decimal_count_param);
708 if (line.length() > 0) {
709 *ostream << line << endl;
716 log_error("[%s] File open for data save failed: %s\n", device_id.c_str(), fname_param.c_str());
718 if (ostream != NULL) {
724 Data *StoreCache::get_oldest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
729 vector<string> mon_vcr;
730 vector<string> dta_vcr;
739 if (period_type_param == PERIOD_YEARLY) {
740 snprintf(buffer, 30, "%d", date_param->year);
741 year_name.append(buffer);
742 device_dir = DeviceConfig::get_base_dir_name();
743 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
744 year_dr = FileUtil::concat_paths(device_dir, year_name);
745 mon_vcr = FileUtil::get_subdirectories(year_dr);
746 for (ii = 0; ii < mon_vcr.size(); ii++) {
747 mon_dr = mon_vcr.at(ii);
748 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
749 // scan data files from month dir
750 dta_vcr = FileUtil::get_data_files(mon_dr);
751 size = dta_vcr.size();
753 f_name = dta_vcr.at(0);
754 f_name = FileUtil::concat_paths(mon_dr, f_name);
755 store = new StoreDay(f_name);
756 ret_val = store->get_oldest_data();
762 else if (period_type_param == PERIOD_MONTHLY) {
764 snprintf(buffer, 30, "%d", date_param->year);
765 year_name.append(buffer);
766 device_dir = DeviceConfig::get_base_dir_name();
767 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
768 year_dr = FileUtil::concat_paths(device_dir, year_name);
769 snprintf(buffer, 30, "%02d", date_param->month);
770 mon_dr.append(buffer);
771 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
772 // scan data files from month dir
773 dta_vcr = FileUtil::get_data_files(mon_dr);
774 size = dta_vcr.size();
776 f_name = dta_vcr.at(0);
777 f_name = FileUtil::concat_paths(mon_dr, f_name);
778 store = new StoreDay(f_name);
779 ret_val = store->get_oldest_data();
785 store = new StoreDay(device_id_param, date_param);
786 ret_val = store->get_oldest_data();
792 Data *StoreCache::get_latest_data(Date *date_param, string device_id_param, EnumSummaryPeriod period_type_param) {
795 vector<string> mon_vcr;
796 vector<string> dta_vcr;
807 if (period_type_param == PERIOD_YEARLY) {
808 snprintf(buffer, 30, "%d", date_param->year);
809 year_name.append(buffer);
810 device_dir = DeviceConfig::get_base_dir_name();
811 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
812 year_dr = FileUtil::concat_paths(device_dir, year_name);
813 mon_vcr = FileUtil::get_subdirectories(year_dr);
814 for (ii = mon_vcr.size() - 1; ii >= 0; ii--) {
815 mon_dr = mon_vcr.at(ii);
816 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
817 // scan data files from month dir
818 dta_vcr = FileUtil::get_data_files(mon_dr);
819 size = dta_vcr.size();
821 f_name = dta_vcr.at(size - 1);
822 f_name = FileUtil::concat_paths(mon_dr, f_name);
823 store = new StoreDay(f_name);
824 ret_val = store->get_latest_data();
830 else if (period_type_param == PERIOD_MONTHLY) {
832 snprintf(buffer, 30, "%d", date_param->year);
833 year_name.append(buffer);
834 device_dir = DeviceConfig::get_base_dir_name();
835 device_dir = FileUtil::concat_paths(device_dir, device_id_param);
836 year_dr = FileUtil::concat_paths(device_dir, year_name);
837 snprintf(buffer, 30, "%02d", date_param->month);
838 mon_dr.append(buffer);
839 mon_dr = FileUtil::concat_paths(year_dr, mon_dr);
840 // scan data files from month dir
841 dta_vcr = FileUtil::get_data_files(mon_dr);
842 size = dta_vcr.size();
844 f_name = dta_vcr.at(size - 1);
845 f_name = FileUtil::concat_paths(mon_dr, f_name);
846 store = new StoreDay(f_name);
847 ret_val = store->get_latest_data();
853 store = new StoreDay(device_id_param, date_param);
854 ret_val = store->get_latest_data();