diff --git a/src/AlarmHandler.cpp b/src/AlarmHandler.cpp index 0acebd46d6e38141a96e1e3cc786dc1d75c95700..35c3d0b5b3fc81ecf47728f9903271ac3c08a2b4 100644 --- a/src/AlarmHandler.cpp +++ b/src/AlarmHandler.cpp @@ -1922,13 +1922,13 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin) start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' }*/ start_pos = filter.find("*", start_pos); - if(start_pos != std::string::npos && start_pos == filter.size()-1) //* is the only character or at the end of the filter + if(start_pos != std::string::npos && start_pos == filter.size()-1) // * is the only character or at the end of the filter { filter.replace(start_pos, 1, ""); filter_begin = filter; DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin; } - /*else if(start_pos != std::string::npos) //* is in the middle of the filter + /*else if(start_pos != std::string::npos) // * is in the middle of the filter { string filter_begin=filter.substr(0,start_pos); string filter_end=filter.substr(start_pos+1); @@ -3657,6 +3657,7 @@ void AlarmHandler::do_alarm(bei_t& e) } if(found_ev != events->v_event.end()) { + found_ev->valid = false; Tango::TimeVal ts = gettime(); found_ev->err_counter++; if(e.type == TYPE_TANGO_ERR) @@ -3675,10 +3676,15 @@ void AlarmHandler::do_alarm(bei_t& e) list<string>::iterator j = m_alarm.begin(); while (j != m_alarm.end()) { + DEBUG_STREAM << "AlarmHandler::"<<__func__<<": before do_alarm_eval name=" << *j << " ev=" << e.ev_name << " err=" << found_ev_ex_desc << endl; + changed = do_alarm_eval(*j, e.ev_name, ts); + //if(!changed) + // continue; //TODO: check if OK alarms.vlock->readerIn(); alarm_container_t::iterator it = alarms.v_alarm.find(*j); if(it != alarms.v_alarm.end()) { +#if 0 //already done in alarm_table::update called by do_alarm_eval it->second.err_counter++; //if first error, reset ACK if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty()) @@ -3712,8 +3718,11 @@ void AlarmHandler::do_alarm(bei_t& e) } it->second.error = true; } +#endif alarm_t alm = it->second; alarms.vlock->readerOut(); + DEBUG_STREAM << "AlarmHandler::"<<__func__<<": after do_alarm_eval name=" << *j << " error=" << (int)alm.error << " enabled=" << alm.enabled << endl; +#if 0 //TODO: already pushed in do_alarm_eval, not necessary here ? if(alm.error && alm.enabled && !(alm.shelved && alm.silenced > 0)) { try @@ -3731,7 +3740,7 @@ void AlarmHandler::do_alarm(bei_t& e) }catch(Tango::DevFailed &ex) {} } - else + else if(alm.error) //TODO: or if(changed) ? { Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name); if(!alm.enabled) @@ -3755,6 +3764,7 @@ void AlarmHandler::do_alarm(bei_t& e) push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value); } } +#endif } else { @@ -3805,7 +3815,6 @@ void AlarmHandler::do_alarm(bei_t& e) return; } DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl; - formula_res_t res; events->veclock.readerIn(); vector<event>::iterator found = \ find(events->v_event.begin(), events->v_event.end(), e.ev_name); @@ -3973,10 +3982,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal it->second.to_be_evaluated = false; it->second.attr_values.erase(it->second.attr_values.size()-1); it->second.attr_values += string("}"); - DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl; + DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << " valid=" << (int)res.valid << endl; changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); //update internal structure and log to db - changed = changed || prev_error; - DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << endl; + changed = changed || (prev_error && res.valid); + DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl; Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name); if(!it->second.enabled) *attr_value = _OOSRV; @@ -4442,7 +4451,18 @@ void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg, //============================================================== formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_values) { - return eval_expression(tree.trees.begin(), attr_values); + formula_res_t res = eval_expression(tree.trees.begin(), attr_values); +#ifdef _DEBUG_FORMULA + DEBUG_STREAM << __func__ << ": finally value=" << res.value << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"'" << endl; +#endif + if(res.valid) + { + res.ex_reason.clear(); + res.ex_desc.clear(); + res.ex_origin.clear(); + res.error.clear(); + } + return res; } formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range @@ -4462,6 +4482,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values string val_d(i->value.begin(), i->value.end()); formula_res_t res; res.value = strtod(val_d.c_str(), 0); + res.valid = true; #ifdef _DEBUG_FORMULA DEBUG_STREAM << " node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl; #endif @@ -4480,6 +4501,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values #endif formula_res_t res; res.value = strtod(val_d.c_str(), 0); + res.valid = true; return res; } else if (i->value.id() == formula_grammar::val_stID) @@ -4496,6 +4518,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values #endif formula_res_t res; res.value = st; + res.valid = true; return res; } else if (i->value.id() == formula_grammar::val_alarm_enum_stID) @@ -4512,6 +4535,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values #endif formula_res_t res; res.value = st; + res.valid = true; return res; } else if (i->value.id() == formula_grammar::val_qualityID) @@ -4529,6 +4553,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values #endif formula_res_t res; res.value = quality; + res.valid = true; return res; } else if (i->value.id() == formula_grammar::unary_exprID) @@ -4685,8 +4710,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values err << it->ex_desc << ""; else err << "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula"; + formula_res_t res; + res.valid = false; + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + res.error = err.str(); +#ifdef _DEBUG_FORMULA + DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << endl; +#endif events->veclock.readerOut(); - throw err.str(); + //throw err.str(); + return res; } else if(it->type != Tango::DEV_STRING && it->value.empty()) { @@ -4694,8 +4730,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values err << it->ex_desc << ""; else err << "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula"; + formula_res_t res; + res.valid = false; + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + res.error = err.str(); +#ifdef _DEBUG_FORMULA + DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << endl; +#endif events->veclock.readerOut(); - throw err.str(); + //throw err.str(); + return res; } ostringstream temp_attr_val; if(it->value.size() > 1) @@ -4704,6 +4751,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values temp_attr_val << "\"" << it->name << "\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range attr_values += temp_attr_val.str(); formula_res_t res; + res.valid = true; res.quality = it->quality; res.ex_reason = it->ex_reason; res.ex_desc = it->ex_desc; @@ -4734,6 +4782,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values DEBUG_STREAM << " node index = " << val_d << endl; #endif formula_res_t res; + res.valid = true; res.value = strtod(val_d.c_str(), 0); return res; } @@ -4776,6 +4825,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values formula_res_t res_1=eval_expression(i->children.begin(), attr_values), res_2=eval_expression(i->children.begin()+1, attr_values); long val_l1,val_l2; + bool valid = res_1.valid && res_2.valid; string err2("ERROR: non-int value in bitwise operation!"); val_l1 = (long)trunc(res_1.value); //transform to long @@ -4788,30 +4838,42 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values { formula_res_t res; res.value = (double)(val_l1 & val_l2); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else if (*i->value.begin() == '|') { formula_res_t res; res.value = (double)(val_l1 | val_l2); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else if (*i->value.begin() == '^') { formula_res_t res; res.value = (double)(val_l1 ^ val_l2); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else @@ -4833,6 +4895,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values formula_res_t res_1=eval_expression(i->children.begin(), attr_values), res_2=eval_expression(i->children.begin()+1, attr_values); long val_l1,val_l2; + bool valid = res_1.valid && res_2.valid; string err2("ERROR: non-int value in bitwise operation!"); val_l1 = (long)trunc(res_1.value); //transform to long @@ -4845,20 +4908,28 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values { formula_res_t res; res.value = (double)(val_l1 << val_l2); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else if (string(i->value.begin(), i->value.end()) == string(">>")) { formula_res_t res; res.value = (double)(val_l1 >> val_l2); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else @@ -4918,6 +4989,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ostringstream temp_attr_val; temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\","; attr_values += temp_attr_val.str(); + res.valid = true; res.quality = it->quality; res.ex_reason = it->ex_reason; res.ex_desc = it->ex_desc; @@ -5066,8 +5138,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values err << it->ex_desc << ""; else err << "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula"; + formula_res_t res; + res.valid = false; + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + res.error = err.str(); +#ifdef _DEBUG_FORMULA + DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << endl; +#endif events->veclock.readerOut(); - throw err.str(); + //throw err.str(); + return res; } else if(it->type != Tango::DEV_STRING && it->value.empty()) { @@ -5075,8 +5158,19 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values err << it->ex_desc << ""; else err << "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula"; + formula_res_t res; + res.valid = false; + res.quality = it->quality; + res.ex_reason = it->ex_reason; + res.ex_desc = it->ex_desc; + res.ex_origin = it->ex_origin; + res.error = err.str(); +#ifdef _DEBUG_FORMULA + DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << endl; +#endif events->veclock.readerOut(); - throw err.str(); + //throw err.str(); + return res; } ostringstream temp_attr_val; @@ -5147,34 +5241,47 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values } formula_res_t res_1=eval_expression(i->children.begin(), attr_values), res_2=eval_expression(i->children.begin()+1, attr_values); + bool valid = res_1.valid && res_2.valid; if (string(i->value.begin(), i->value.end()) == string("min")) { formula_res_t res; res.value = min(res_1.value, res_2.value); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else if (string(i->value.begin(), i->value.end()) == string("max")) { formula_res_t res; res.value = max(res_1.value, res_2.value); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else if (string(i->value.begin(), i->value.end()) == string("pow")) { formula_res_t res; res.value = pow(res_1.value, res_2.value); + res.valid = valid; res.quality = res.combine_quality(res_1.quality, res_2.quality); - res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); - res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); - res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + if(!res.valid) + { + res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); + res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); + res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); + } return res; } else @@ -5217,6 +5324,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values } formula_res_t res; res.value = 0; + res.valid = false; return res; } @@ -5308,7 +5416,7 @@ void AlarmHandler::prepare_alarm_attr() } else { - if(ai->second.stat == S_ALARM && ai->second.ack == ACK) + if(ai->second.stat == S_ALARM && ai->second.ack == ACK && !ai->second.error) { acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name; attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str()); @@ -5318,7 +5426,7 @@ void AlarmHandler::prepare_alarm_attr() acknowledgedAlarms_sz++; almstate = "ACKED"; } - else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK) + else if(ai->second.stat == S_ALARM && ai->second.ack == NOT_ACK && !ai->second.error) { unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name; attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str()); @@ -5328,7 +5436,7 @@ void AlarmHandler::prepare_alarm_attr() unacknowledgedAlarms_sz++; almstate = "UNACK"; } - else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK) + else if(ai->second.stat == S_NORMAL && ai->second.ack == NOT_ACK && !ai->second.error) { unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name; attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str()); @@ -5338,7 +5446,7 @@ void AlarmHandler::prepare_alarm_attr() unacknowledgedNormalAlarms_sz++; almstate = "RTNUN"; } - else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK) + else if(ai->second.stat == S_NORMAL && ai->second.ack == ACK && !ai->second.error) { normalAlarms_read[normalAlarms_sz] = ai->second.name; attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str()); diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp index 47c7763905ae37f7f770d4d72c32ea29aee8ff4f..64f1badd7fd0bf274691e6272b16b63daf4c65a6 100644 --- a/src/alarm_table.cpp +++ b/src/alarm_table.cpp @@ -356,9 +356,18 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_ } bool status_err_delay; if(err_delay > 0) - status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty()) && (found->second.err_counter >= 1) && ((now.tv_sec - err_delay) > found->second.ts_err_delay.tv_sec); //error is present and err delay has passed + status_err_delay = (!res.valid) && (found->second.err_counter >= 1) && ((now.tv_sec - err_delay) > found->second.ts_err_delay.tv_sec); //error is present and err delay has passed else - status_err_delay = (!res.ex_reason.empty() || !res.ex_desc.empty() || !res.ex_origin.empty()); + status_err_delay = (!res.valid); + if(!status_err_delay && !res.valid) //formula result not valid, waiting for err_delay + { + found->second.attr_values_delay = attr_values; //save last attr_values to be used in timer_update if this alarm pass over on or off delay + found->second.err_counter++; + if(found->second.err_counter == 1) + found->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay + vlock->readerOut(); + return ret_changed; + } found->second.quality = res.quality; found->second.ex_reason = res.ex_reason; found->second.ex_desc = res.ex_desc; @@ -523,7 +532,7 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_ found->second.on_counter = 0; found->second.off_counter++; } - if(!found->second.ex_reason.empty() || !found->second.ex_desc.empty() || !found->second.ex_origin.empty()) + if(!res.valid) { found->second.err_counter++; } @@ -566,7 +575,7 @@ bool alarm_table::timer_update() bool status_on_delay=false; bool status_off_delay=false; bool status_err_delay=false; - if(err_delay > 0) //if enabled off delay + if(err_delay > 0) //if enabled err delay status_err_delay = (i->second.err_counter >= 1) && ((ts.tv_sec - err_delay) > i->second.ts_err_delay.tv_sec); //waiting for err delay has passed if(i->second.on_delay == 0 && i->second.off_delay == 0 && err_delay == 0 && !i->second.shelved && i->second.silenced <=0) diff --git a/src/alarm_table.h b/src/alarm_table.h index 3d0bc84dce35b564c53ec325b3ec2fb23433d5f2..321b8e3ac7f47b0a3e6cd2c051985b8626eea68e 100644 --- a/src/alarm_table.h +++ b/src/alarm_table.h @@ -112,9 +112,11 @@ struct rwlock_t struct formula_res_t { - formula_res_t(){value=0;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");} + formula_res_t(){value=0;valid=false;quality=Tango::ATTR_VALID;ex_reason=string("");ex_desc=string("");ex_origin=string("");} double value; int quality; + bool valid; + string error; Tango::DevErrorList errors; //TODO: error stack string ex_reason; string ex_desc; @@ -145,120 +147,168 @@ struct formula_res_t { formula_res_t res; res.value = value == e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator!=(const formula_res_t& e) { formula_res_t res; res.value = value != e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator<=(const formula_res_t& e) { formula_res_t res; res.value = value <= e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator>=(const formula_res_t& e) { formula_res_t res; res.value = value >= e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator<(const formula_res_t& e) { formula_res_t res; res.value = value < e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator>(const formula_res_t& e) { formula_res_t res; res.value = value > e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator||(const formula_res_t& e) { formula_res_t res; - res.value = value || e.value; + res.value = (valid && value) || (e.valid && e.value); + res.valid = (valid && value) || (e.valid && e.value) || (valid && e.valid); res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator&&(const formula_res_t& e) { formula_res_t res; - res.value = value && e.value; + res.value = !((valid && !value) || (e.valid && !e.value)) || (valid && value && e.valid && e.value); + res.valid = (valid && !value) || (e.valid && !e.value) || (valid && e.valid); res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator+(const formula_res_t& e) { formula_res_t res; res.value = value + e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator-(const formula_res_t& e) { formula_res_t res; res.value = value - e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator*(const formula_res_t& e) { formula_res_t res; res.value = value * e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } formula_res_t operator/(const formula_res_t& e) { formula_res_t res; res.value = value / e.value; + res.valid = valid && e.valid; res.quality = combine_quality(quality, e.quality); - res.ex_reason = combine_exception(ex_reason, e.ex_reason); - res.ex_desc = combine_exception(ex_desc, e.ex_desc); - res.ex_origin = combine_exception(ex_origin, e.ex_origin); + if(!res.valid) + { + res.ex_reason = combine_exception(ex_reason, e.ex_reason); + res.ex_desc = combine_exception(ex_desc, e.ex_desc); + res.ex_origin = combine_exception(ex_origin, e.ex_origin); + } return res; } /*string operator<<(const formula_res_t& e)