4 * Created on: Jan 6, 2011
10 #include "StoreCache.hh"
11 #include "StoreDay.hh"
12 #include "DeviceConfig.hh"
13 #include "DeviceData.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 = W1Util::concat_paths(bd_name, CACHE_DIR_NAME);
37 bd_name = W1Util::concat_paths(bd_name, device_id_param);
38 bd_name = W1Util::concat_paths(bd_name, SUMMARY_PERIOD_NAMES_ARRAY[period_type_param]);
39 bd_name = W1Util::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 = W1Util::concat_paths(ret_val, fname);
83 DataRange *StoreCache::get_mean(EnumSummaryPeriod period_type_param) {
90 fname = get_file_name(device_id,
94 if (store_data == NULL) {
95 if (access(fname.c_str(), R_OK) == 0) {
99 if (store_data != NULL) {
100 row_count = store_data->get_count();
102 ret_val = new DataRange();
103 dta = store_data->get(0);
108 if (ret_val == NULL) {
109 switch(period_type_param) {
123 cur_date = date->clone();
124 max_date = date->clone();
125 if (period_type_param == PERIOD_YEARLY) {
126 max_date->next_year();
129 max_date->next_month();
134 while(cur_date->before(max_date)) {
135 if (period_type_param == PERIOD_YEARLY) {
136 store = new StoreCache(device_id, cur_date);
137 dr = store->get_mean(PERIOD_MONTHLY);
140 store = new StoreDay(device_id, cur_date);
141 dr = store->get_mean(PERIOD_DAILY);
144 cur_data = dr->get_first();
145 if (cur_data != NULL) {
147 if (res_data == NULL) {
149 val_cnt = res_data->get_value_count();
152 for (ii = 0; ii < val_cnt; ii++) {
153 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
161 if (period_type_param == PERIOD_YEARLY) {
162 cur_date->next_month();
165 cur_date->next_day();
168 if ((res_data != NULL) &&
170 for (ii = 0; ii < val_cnt; ii++) {
171 res_data->value_arr[ii] = res_data->value_arr[ii] / cnt;
173 ret_val = new DataRange(res_data);
174 save(fname, ret_val, 4);
183 case PERIOD_MINUTELY:
184 case PERIOD_SECONDLY: {
187 store = new StoreDay(device_id, date);
188 ret_val = store->get_mean(period_type_param);
189 if ((period_type_param != PERIOD_MINUTELY) ||
190 (period_type_param != PERIOD_SECONDLY)) {
191 // no need cache second or minute data
192 save(fname, ret_val, 4);
202 DataRange *StoreCache::get_sum(EnumSummaryPeriod period_type_param) {
210 fname = get_file_name(device_id,
214 if (store_data == NULL) {
215 if (access(fname.c_str(), R_OK) == 0) {
219 if (store_data != NULL) {
220 row_count = store_data->get_count();
222 ret_val = new DataRange();
223 dta = store_data->get(0);
228 if (ret_val == NULL) {
229 switch(period_type_param) {
231 case PERIOD_MONTHLY: {
241 cur_date = date->clone();
242 max_date = date->clone();
243 if (period_type_param == PERIOD_YEARLY) {
244 max_date->next_year();
247 max_date->next_month();
252 while(cur_date->before(max_date)) {
253 if (period_type_param == PERIOD_YEARLY) {
254 store = new StoreCache(device_id, cur_date);
255 dr = store->get_sum(PERIOD_MONTHLY);
258 store = new StoreDay(device_id, cur_date);
259 dr = store->get_sum(PERIOD_DAILY);
262 cur_data = dr->get_first();
263 if (cur_data != NULL) {
265 if (res_data == NULL) {
269 val_cnt = res_data->get_value_count();
270 for (ii = 0; ii < val_cnt; ii++) {
271 res_data->value_arr[ii] = res_data->value_arr[ii] + cur_data->value_arr[ii];
279 if (period_type_param == PERIOD_YEARLY) {
280 cur_date->next_month();
283 cur_date->next_day();
286 if ((res_data != NULL) &&
288 ret_val = new DataRange(res_data);
289 save(fname, ret_val, 4);
298 case PERIOD_MINUTELY:
299 case PERIOD_SECONDLY:
300 store = new StoreDay(device_id, date);
301 ret_val = store->get_sum(period_type_param);
302 if ((period_type_param != PERIOD_MINUTELY) ||
303 (period_type_param != PERIOD_SECONDLY)) {
304 // no need cache second or minute data
305 save(fname, ret_val, 4);
314 DataRange *StoreCache::get_delta(EnumSummaryPeriod period_type_param) {
322 fname = get_file_name(device_id,
326 if (store_data == NULL) {
327 if (access(fname.c_str(), R_OK) == 0) {
328 // read from cache file
332 if (store_data != NULL) {
333 row_count = store_data->get_count();
335 ret_val = new DataRange();
336 dta = store_data->get(0);
341 if (ret_val == NULL) {
342 switch(period_type_param) {
343 case PERIOD_YEARLY: {
349 first_data = get_year_oldest_data();
350 if (first_data != NULL) {
351 last_data = get_year_newest_data();
352 if (last_data != NULL) {
353 ret_val = new DataRange();
354 cnt = last_data->get_value_count();
355 for (ii = 0; ii < cnt; ii++) {
356 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
358 ret_val->add(last_data);
362 save(fname, ret_val, 4);
365 log_error("Could not read first or last data item from device %s for year: %d", device_id.c_str(), date->year);
369 case PERIOD_MONTHLY: {
378 cur_date = date->clone();
379 limit_date = date->clone();
380 limit_date->next_month();
383 while(cur_date->before(limit_date)) {
384 store = new StoreDay(device_id, cur_date);
385 if (first_data == NULL) {
386 cur_data = store->get_oldest_data();
387 if (cur_data != NULL) {
388 first_data = cur_data->clone();
389 last_data = cur_data->clone();
393 cur_data = store->get_newest_data();
394 if (cur_data != NULL) {
395 if (last_data != NULL) {
398 last_data = cur_data;
401 cur_date->next_day();
405 if (first_data != NULL) {
406 if (last_data == NULL) {
407 last_data = first_data->clone();
409 cnt = last_data->get_value_count();
410 for (ii = 0; ii < cnt; ii++) {
411 last_data->value_arr[ii] = last_data->value_arr[ii] - first_data->value_arr[ii];
413 cur_date = first_data->get_date().clone();
414 last_data->set_date(cur_date);
416 ret_val = new DataRange(last_data);
419 save(fname, ret_val, 4);
425 case PERIOD_MINUTELY:
426 case PERIOD_SECONDLY:
427 store = new StoreDay(device_id, date);
428 ret_val = store->get_delta(period_type_param);
429 if ((period_type_param != PERIOD_MINUTELY) ||
430 (period_type_param != PERIOD_SECONDLY)) {
431 // no need cache second or minute data
432 save(fname, ret_val, 4);
441 DataRange *StoreCache::get_max(EnumSummaryPeriod period_type_param) {
449 fname = get_file_name(device_id,
453 if (store_data == NULL) {
454 if (access(fname.c_str(), R_OK) == 0) {
458 if (store_data != NULL) {
459 row_count = store_data->get_count();
461 ret_val = new DataRange();
462 dta = store_data->get(0);
467 if (ret_val == NULL) {
468 switch(period_type_param) {
470 case PERIOD_MONTHLY: {
480 cur_date = date->clone();
481 max_date = date->clone();
482 if (period_type_param == PERIOD_YEARLY) {
483 max_date->next_year();
486 max_date->next_month();
491 while(cur_date->before(max_date)) {
492 if (period_type_param == PERIOD_YEARLY) {
493 store = new StoreCache(device_id, cur_date);
494 dr = store->get_max(PERIOD_MONTHLY);
497 store = new StoreDay(device_id, cur_date);
498 dr = store->get_max(PERIOD_DAILY);
501 cur_data = dr->get_first();
502 if (cur_data != NULL) {
504 if (res_data == NULL) {
508 val_cnt = res_data->get_value_count();
510 for (ii = 0; ii < val_cnt; ii++) {
511 if (cur_data->value_arr[ii] > res_data->value_arr[ii]) {
512 res_data->value_arr[ii] = cur_data->value_arr[ii];
519 new_date = cur_data->get_date();
520 res_data->set_date(&new_date);
528 if (period_type_param == PERIOD_YEARLY) {
529 cur_date->next_month();
532 cur_date->next_day();
535 if ((res_data != NULL) &&
537 ret_val = new DataRange(res_data);
538 save(fname, ret_val, 4);
547 case PERIOD_MINUTELY:
548 case PERIOD_SECONDLY:
549 store = new StoreDay(device_id, date);
550 ret_val = store->get_max(period_type_param);
551 if ((period_type_param != PERIOD_MINUTELY) ||
552 (period_type_param != PERIOD_SECONDLY)) {
553 // no need cache second or minute data
554 save(fname, ret_val, 4);
563 DataRange *StoreCache::get_min(EnumSummaryPeriod period_type_param) {
571 fname = get_file_name(device_id,
575 if (store_data == NULL) {
576 if (access(fname.c_str(), R_OK) == 0) {
580 if (store_data != NULL) {
581 row_count = store_data->get_count();
583 ret_val = new DataRange();
584 dta = store_data->get(0);
589 if (ret_val == NULL) {
590 switch(period_type_param) {
592 case PERIOD_MONTHLY: {
602 cur_date = date->clone();
603 max_date = date->clone();
604 if (period_type_param == PERIOD_YEARLY) {
605 max_date->next_year();
608 max_date->next_month();
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 = W1Util::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) {
720 * Find oldest data in certain year
722 Data *StoreCache::get_year_oldest_data() {
725 DeviceData *dta_finder;
728 dta_finder = new DeviceData(device_id);
729 snprintf(buffer, 30, "%d", date->year);
731 ret_val = dta_finder->find_oldest_data(str);
737 * Find newest data in certain year
739 Data *StoreCache::get_year_newest_data() {
742 DeviceData *dta_finder;
745 dta_finder = new DeviceData(device_id);
746 snprintf(buffer, 30, "%d", date->year);
748 ret_val = dta_finder->find_newest_data(str);