Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cs/ds/alarm-handler
  • francesco.tripaldi/alarm-handler
2 results
Show changes
Commits on Source (51)
Showing
with 1884 additions and 359 deletions
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*.out *.out
*.app *.app
bin/ bin/
build/
.nse_depinfo .nse_depinfo
......
image:
name: harbor.skao.int/production/ska-tango-images-tango-dsconfig:1.5.5
stages:
- build
- test
build_job:
stage: build
tags:
- docker
before_script:
- sudo apt update && sudo apt -y --no-install-recommends install build-essential cmake pkg-config libboost-thread-dev
script:
- mkdir build && cd build
- cmake -DBUILD_TESTS=ON ..
- make
artifacts:
paths:
- build/alarm-handler-srv
- build/bin/testdevice-srv
expire_in: 1 week
test_load_job:
stage: test
tags:
- docker
before_script:
- sudo apt update && sudo apt -y --no-install-recommends install libboost-thread-dev
script:
- sleep 10
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- exit_code=2
- json2tango -w -a -u ./test/ah_config.json || exit_code=$?
- if [ ${exit_code} -ne 2 ]; then echo "Tango DB configuration failed!" ; else echo "Tango DB configuration succedeed!"; fi
- ./build/alarm-handler-srv 01 &
- ./build/bin/testdevice-srv 01 &
- sleep 5
- python ./test/load-alarm-conf.py --device=alarm/handler/01 --load="tag=test0;formula=(alarm/test/01/condition == 1);on_delay=0;off_delay=0;priority=high;shlvd_time=0;group=gr_test;message=Test alarm;url=;on_command=;off_command=;enabled=1"
- sleep 1
- python ./test/check-alarm-conf.py --device=alarm/handler/01 --alarm="tag=test0;formula=(alarm/test/01/condition == 1);on_delay=0;off_delay=0;priority=high;shlvd_time=0;group=gr_test;message=Test alarm;url=;on_command=;off_command=;enabled=1"
needs: ["build_job"]
services:
- name: harbor.skao.int/production/ska-tango-images-tango-db:10.4.16
alias: tangodb
image:
name: harbor.skao.int/production/ska-tango-images-tango-dsconfig:1.5.5
# The following variables are automatically passed down to the tangodb container
# as well as the tangodatabaseds container and available within each.
variables:
MYSQL_ROOT_PASSWORD: "secret"
MYSQL_DATABASE: "tango"
MYSQL_USER: "tango"
MYSQL_PASSWORD: "tango"
MYSQL_HOST: "tangodb"
TANGO_HOST: "localhost:10000"
stages:
- build
- conf
- test
services:
- name: harbor.skao.int/production/ska-tango-images-tango-db
alias: tangodb
# - name: harbor.skao.int/production/ska-tango-images-tango-cpp
# alias: tangodatabaseds
# entrypoint: ["/usr/local/bin/DataBaseds"]
# command: ["2","-ORBendPoint giop:tcp::10000"]
build_job:
stage: build
before_script:
#TODO: remove procps use for ps
- sudo apt update && sudo apt -y --no-install-recommends install build-essential cmake pkg-config libboost-thread-dev procps
script:
#- make
- mkdir build && cd build
- cmake ..
- make
artifacts:
paths:
- build/alarm-handler-srv
expire_in: 1 week
# # depending on your build setup it's most likely a good idea to cache outputs to reduce the build time
# cache:
# paths:
# - build/CMakeFiles/
configure_and_run_job:
stage: conf
script:
- sleep 10
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- exit_code=2
- json2tango -w -a -u ./test/ah_config.json || exit_code=$?
# json2tango returns 2 if values written to DB
- if [ ${exit_code} -ne 2 ]; then echo "Tango DB configuration failed!" ; else echo "Tango DB configuration succedeed!"; fi
- sleep 5
artifacts:
paths:
- build/alarm-handler-srv
expire_in: 1 week
needs: ["build_job"]
#services:
# - name: harbor.skao.int/production/ska-tango-images-tango-db
# alias: tangodb
test_job:
stage: test
before_script:
#TODO: remove procps use for ps
- sudo apt update && sudo apt -y --no-install-recommends install libboost-thread-dev procps
script:
- /usr/local/bin/DataBaseds 2 -ORBendPoint giop:tcp::10000 &
- sleep 10
- ./build/alarm-handler-srv 01 &
- sleep 10
- ps -ef | grep alarm-handler-srv | grep -v grep
- sleep 5
needs: ["configure_and_run_job"]
# Functions and Pre-build -----------------------------------
# Stop messy in source builds
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES OFF)
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()
# Start Build Config -----------------------------------
cmake_minimum_required(VERSION 3.8)
set(CMAKE_SKIP_RPATH true)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_COLOR_MAKEFILE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Output name for the final binary
set(AH_NAME "alarm-handler-srv")
# Versioning
set(VERSION_MAJOR "1")
set(VERSION_MINOR "0")
set(VERSION_PATCH "0")
set(VERSION_METADATA "")
set(VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
# Add any include paths from the command line
list(APPEND INCLUDE_PATHS ${CMAKE_INCLUDE_PATH})
list(APPEND INCLUDE_PATHS ${CMAKE_SOURCE_DIR})
list(APPEND LIBRARY_PATHS ${CMAKE_LIBRARY_PATH})
# Start the project
project(alarm_handler VERSION ${VERSION_STRING} LANGUAGES CXX)
# Build options
option(ENABLE_CLANG "Enable clang code and layout analysis" OFF)
option(BUILD_TESTS "Build tests" OFF)
# arch install definitions
include(GNUInstallDirs)
message(STATUS "Searching for libraries...")
# Variable to contain a list of all the libs we depend on
set(AH_LIBRARIES)
# allow pkg-config to search the CMAKE_PREFIX_PATH
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON)
list(APPEND CMAKE_PREFIX_PATH "/usr")
# Find Dependencies -----------------------------------
# Find tango if it has not already been found. Returns an interface library
# called TangoInterfaceLibrary
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(Tango)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.65.0 COMPONENTS thread)
# Code Analysis -----------------------------------
if(ENABLE_CLANG)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# To find clang, find_program will search your PATH environment variable.
# Ensure if you have a non-standard clang install, that it has been added
# to your path.
find_program(CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable")
if(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy not found.")
else(NOT CLANG_TIDY_EXE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}")
endif(NOT CLANG_TIDY_EXE)
endif(ENABLE_CLANG)
# Source -----------------------------------
add_subdirectory(src)
# Build Targets -----------------------------------
# Executable --------
add_executable(alarm_handler ${SRC_FILES})
target_link_libraries(alarm_handler
PRIVATE
TangoInterfaceLibrary
${Boost_LIBRARIES}
)
target_include_directories(alarm_handler
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
${INCLUDE_PATHS}
"${PROJECT_BINARY_DIR}"
${Boost_INCLUDE_DIRS})
if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set_target_properties(alarm_handler
PROPERTIES
OUTPUT_NAME ${AH_NAME}
LINK_FLAGS "-Wl,--no-undefined"
CXX_STANDARD 17)
else()
set_target_properties(alarm_handler
PROPERTIES
OUTPUT_NAME ${AH_NAME}
LINK_FLAGS ""
CXX_STANDARD 17)
endif()
if(DO_CLANG_TIDY)
set_target_properties(alarm_handler
PROPERTIES
CXX_CLANG_TIDY ${DO_CLANG_TIDY})
endif(DO_CLANG_TIDY)
target_compile_options(alarm_handler
PRIVATE "$<$<CONFIG:DEBUG>:-g>")
# Install Config -----------------------------------
install(
TARGETS alarm_handler
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
message(STATUS "Configured alarm-handler project")
# Tests -----------------------------------
if(BUILD_TESTS)
add_subdirectory(test)
endif(BUILD_TESTS)
# alarm # Alarm-handler
Elettra alarm-handler Tango device Elettra alarm-handler Tango device
## building ## Building and Installation
git clone http://github.com/ELETTRA-SincrotroneTrieste/makefiles.git
git clone http://github.com/ELETTRA-SincrotroneTrieste/alarm-handler.git In its simplest form, clone the repository and assuming a standard install for all dependencies:
cd alarm-handler ```
mkdir build
cd build
cmake ../
make
make install
```
### pkg-config Settings
The build system uses pkg-config to find some dependencies, for example Tango. If Tango is not installed to a standard location, set PKG_CONFIG_PATH, i.e.
```bash
export PKG_CONFIG_PATH=/non/standard/tango/install/location
...
cmake ../
...
```
The pkg-config path can also be set with the cmake argument CMAKE_PREFIX_PATH. This can be set on the command line at configuration time, i.e.:
```bash
...
cmake -DCMAKE_PREFIX_PATH=/non/standard/tango/install/location ../
...
```
### Project Flags
| Flag | Setting | Default | Description |
|------|-----|-----|-----|
| BUILD_TESTS | ON/OFF | OFF | Build test devices under test directory |
### Standard CMake Flags
The build system is CMake therefore standard CMake flags can be used to influence the build and installation process. The following is a list of common useful CMake flags and their use:
| Flag | Use |
|------|-----|
| CMAKE_INSTALL_PREFIX | Standard CMake flag to modify the install prefix. |
| CMAKE_INCLUDE_PATH | Standard CMake flag to add include paths to the search path. |
| CMAKE_LIBRARY_PATH | Standard CMake flag to add paths to the library search path |
## Legacy Building
Using Elettra makefiles, clone both alarm-handler and makefile repositories, then call make:
```bash
git clone http://gitlab.elettra.eu/cd/ds/makefiles.git
git clone http://gitlab.elettra.eu/cs/ds/alarm-handler.git
cd alarm-handler
make make
```
include(CMakeParseArguments)
function(find_libraries)
# Parse the parameters
set(MULTIVALUEARGS LIBRARIES SEARCH_PATHS)
cmake_parse_arguments(FIND_LIBRARIES "" "" "${MULTIVALUEARGS}" ${ARGN})
# Clear the found libraries
unset(FOUND_LIBRARIES PARENT_SCOPE)
foreach(LIB ${FIND_LIBRARIES_LIBRARIES})
# try the user provided paths first
find_library(FOUND_LIB_${LIB} ${LIB} PATHS ${FIND_LIBRARIES_SEARCH_PATHS} NO_DEFAULT_PATH)
# if we could not find it, drop to the system paths
if(NOT FOUND_LIB_${LIB})
find_library(FOUND_LIB_${LIB} ${LIB})
endif(NOT FOUND_LIB_${LIB})
if(FOUND_LIB_${LIB})
message(STATUS "Found " ${LIB} " at: " ${FOUND_LIB_${LIB}})
list(APPEND FOUND_LIBRARIES ${FOUND_LIB_${LIB}})
else()
message(FATAL "Could not find " ${LIB})
endif(FOUND_LIB_${LIB})
endforeach(LIB ${LIBRARIES})
set(FOUND_LIBRARIES ${FOUND_LIBRARIES} PARENT_SCOPE)
endfunction(find_libraries)
\ No newline at end of file
if(NOT TARGET TangoInterfaceLibrary)
# Ensure pkg-config is installed
find_package(PkgConfig REQUIRED)
# Now search for the tango.pc file, this is a required dependency
message(STATUS "Search for TANGO package config...")
pkg_search_module(TANGO REQUIRED tango>=9.2.5)
message(STATUS "Found tango version ${TANGO_VERSION} at ${TANGO_PREFIX}")
include(FindLibraries)
find_libraries(LIBRARIES ${TANGO_LIBRARIES} SEARCH_PATHS ${TANGO_LIBRARY_DIRS})
# Create an interface library to represent the tango linkage
add_library(TangoInterfaceLibrary INTERFACE)
set_target_properties(TangoInterfaceLibrary
PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${TANGO_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${FOUND_LIBRARIES}"
INTERFACE_COMPILE_OPTIONS "${TANGO_CFLAGS}")
message(STATUS "Configured Tango Interface for TANGO version ${TANGO_VERSION}")
endif(NOT TARGET TangoInterfaceLibrary)
\ No newline at end of file
File added
# Formula syntax
The formula is an expression with operators, operands and functions. Operands can be variables, constant values, or other expression optionally enclosed by parentheses.
## Operands
### Variables
- Attributes names with or without fqdn (e.g. ```tango://host:port/name/of/dev/attr```, ```name/of/dev/attr```)
- attribute properties ```.quality```, ```.alarm```, ```.normal``` so that
- ```name/of/dev/attr.quality``` returns the Tango quality (the integer value) of the attribute
- ```name/of/dev/attr.alarm``` returns true if the attribute ==UNACK or ==ACK
- ```name/of/dev/attr.normal``` returns true if the attribute ==NORM or ==RTNUN
### Constants
- Real numbers (e.g. ```name/of/dev/attr >= 35```, ```name/of/dev/attr < -23.5```)
- Hexadecimal numbers (e.g. ```name/of/dev/attr != 0xaf```, ```name/of/dev/attr & 0x1A```)
- Strings as any character between an opening and a closing ' (e.g. ```name/of/dev/status == 'The device is in ON state.'```)
- Tango states enum labels (*ON, OFF, CLOSE, OPEN, INSERT, EXTRACT, MOVING, STANDBY, FAULT, INIT, RUNNING, ALARM, DISABLE, UNKNOWN*) (e.g. ```name/of/dev/state == FAULT```)
- Tango quality enum labels (*ATTR_VALID, ATTR_INVALID, ATTR_WARNING, ATTR_ALARM, ATTR_CHANGING*) (e.g. ```name/of/dev/attr.quality == ATTR_ALARM```)
- Alarm state enum labels (*NORM, UNACK, ACKED, RTNUN, SHLVD, DSUPR, OOSRV*) (e.g. ```name/of/dev/alarm_attr != NORM```)
### Expressions
- A combination of operands and operators enclosed by parentheses
## Operators
### Binary Math
- Multiplication ```*```
- Division ```/```
- Addition ```+```
- Subtraction ```-```
### Binary Comparison
- Equal ```==```
- Not equal ```!=```
- Greater than ```>```
- Greater than or equal to ```>=```
- Less than ```<```
- Less than or equal to ```<=```
### Binary Logical
- Logical AND ```&&```
- Logical OR ```||```
### Binary Bitwise
- Left shift ```<<```
- Right shift ```>>```
- Bitwise AND ```&```
- Bitwise OR ```|```
- Bitwise XOR ```^```
### Unary Math
- Minus ```-```
### Unary Logical
- Logical NOT ```!```
### Binary operators order of precedence
```
*, /, +, -, <<, >>, <=, >=, >, <, ==, !=, &, |, ^, &&, ||
```
## Functions
### Unary Functions
- Absolute value of X ```abs(X)```
- Sine of X ```sin(X)```
- Cosine of X ```cos(X)```
### Binary Functions
- Minimum between two values X and Y ```min(X,Y)```
- Maximum between two values X and Y ```max(X,Y)```
- Power: X raised to the power of Y ```pow(X,Y)```
### Ternary Functions
- Conditional operator: if X then Y else Z ```X ? Y : Z```
### Reduce Functions
- Reduce OR: reduce array X applying logical OR to each element ```OR(X)```
- Reduce AND: reduce array X applying logical AND to each element ```OR(X)```
# Attributes types
The following types of attribute are supported:
```
Scalar, Spectrum, Image
```
with data types:
```
DevBoolean, DevUChar, DevShort, DevUShort, DevLong, DevULong, DevLong64, DevULong64, DevFloat, DevDouble, DevString, DevState, DevEnum
```
```DevEncoded``` is not supported.
The read part of every attribute is internally extracted in a vector of double with the ```extract_read``` method of the ```DeviceAttribute``` class. In this ways operations between attribute with different data types and sizes can be performed with the following constraints:
- DevString attributes can only be compared with 'equal' or 'not equal' operators to DevString attributes or string constants
- Binary operators can operate on arrays if both operands have the same size, or one of the two has size equal to one.
# Operation on arrays
## Indexes to access elements
- A single element of a one-dimensional array attribute (Spectrum) can be extracted with a single index between square brackets (e.g. ```name/of/dev/attr[ind]```).
- A single element of a two-dimensional array attribute (Image) can be extracted with two indexes between square brackets (e.g. ```name/of/dev/attr[ind_row][ind_column]```).
- A one-dimensional array can be extracted from a two-dimensional array attribute (Image) with a single index between square brackets (e.g. ```name/of/dev/attr[ind_row]```).
## Lists and ranges of indexes to slice arrays
Indexes can be specified as a comma separated list and/or hyphen-separated range (e.g. ```[i0,i1-i2,...]```).
In this way:
- A slice can be extracted from a one-dimensional array with a list and/or range of indexes between square brackets (e.g. ```name/of/dev/1Dattr[i0,i1-i2,...]```).
- A subset of rows can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...]```).
- A single column slice can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension and a single index for the second dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...][i3]```).
- A single row slice can be extracted from a two-dimensional array with a single index for the first dimension and list/range of indexes for the second dimension (e.g. ```name/of/dev/2Dattr[i0][i1-i2,i3,...]```).
- An array slice can be extracted from a two-dimensional array with a list and/or range of indexes for both the first and second dimensions (e.g. ```name/of/dev/2Dattr[i0-i1,...][i2,i3,...]```).
- To specify all elements of one dimension index -1 can be used (e.g. Column 3 of all rows of 2D array ```name/of/dev/2Dattr[-1][3]```).
If any index exceeds actual dimensions of the array, the formula is evaluated to ERROR with an out of bounds exception.
No check is done on the order and uniqueness of indexes, so it is allowed to concatenate duplicated and out of order elements/rows/columns (e.g. ```name/of/dev/2Dattr[0-2,1,0,..]``` evaluates to an array with rows 0,1,2,1,0 of 2Dattr)
## Limitations
- It is not possible to specify array constants (e.g. ```name/of/dev/attr > [val1,val2]```).
- It is not possible to use indexes on expressions (e.g. ```(any_expression)[ind]```).
## Unary operators and functions
Unary operators and functions are applied to every element of the array
## Binary operators and functions
- If both operands have the same size, operators are applied element by element. Result is an array with the same size.
- If one operand has size one, operators apply it to every element of the other operand. Result is an array with the same size.
- Otherwise an exception is raised and the formula is evaluated to the *ERROR* state with the Reason, Descrption and Origin DevFailed fields properly filled.
## Ternary Function
- Conditional operator: if X then Y else Z. X is implicitly reduced with *OR* to have a boolean value, then Y or Z are evaluated depending on the result
# Formula result
Every formula produce a boolean result in the following way:
1. each element of the array is tested as not equal to zero in order to have an array of booleans
2. the array of boolean is reduced with OR (i.e. if at least one element of the array is TRUE, the result is TRUE)
# Errors
If a formula cannot be evaluated, the corresponding alarm is set to the *ERROR* value with the Reason, Description and Origin DevFailed fields properly filled.
Possible errors are:
- Errors coming from the event system for one or more attributes involved in the formula
- Errors coming from evaluation of array with different sizes
- Errors coming from indexes out of bound while extracting elements from arrays
- Unexpected errors while evaluating formulas
File added
File added
File added
File added
File added
File added
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <AlarmHandler.h> #include <AlarmHandler.h>
#include <AlarmHandlerClass.h> #include <AlarmHandlerClass.h>
#include <ctype.h> //for tolower #include <ctype.h> //for tolower
#include <numeric> //for std::accumulate
#include "alarm-thread.h" #include "alarm-thread.h"
#include "alarm_grammar.h" #include "alarm_grammar.h"
...@@ -130,6 +131,7 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $"; ...@@ -130,6 +131,7 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";
// alarmSummary | Tango::DevString Spectrum ( max = 10000) // alarmSummary | Tango::DevString Spectrum ( max = 10000)
// eventList | Tango::DevString Spectrum ( max = 10000) // eventList | Tango::DevString Spectrum ( max = 10000)
// eventSummary | Tango::DevString Spectrum ( max = 10000) // eventSummary | Tango::DevString Spectrum ( max = 10000)
// alarmDisabled | Tango::DevString Spectrum ( max = 10000)
//================================================================ //================================================================
namespace AlarmHandler_ns namespace AlarmHandler_ns
...@@ -342,6 +344,7 @@ void AlarmHandler::delete_device() ...@@ -342,6 +344,7 @@ void AlarmHandler::delete_device()
delete[] attr_alarmSummary_read; delete[] attr_alarmSummary_read;
delete[] attr_eventList_read; delete[] attr_eventList_read;
delete[] attr_eventSummary_read; delete[] attr_eventSummary_read;
delete[] attr_alarmDisabled_read;
} }
//-------------------------------------------------------- //--------------------------------------------------------
...@@ -370,7 +373,7 @@ void AlarmHandler::init_device() ...@@ -370,7 +373,7 @@ void AlarmHandler::init_device()
if(instanceCounter > 1) if(instanceCounter > 1)
{ {
ERROR_STREAM << "More than one instance in the same executable of Alarm Server is not allowed!!" << endl; ERROR_STREAM << "More than one instance in the same executable of Alarm Server is not allowed!!" << endl;
cout << "ERROR: second instance of Alarm Server, exiting..." << endl; TANGO_LOG << "ERROR: second instance of Alarm Server, exiting..." << endl;
exit(-1); exit(-1);
} //------------------------------------------- } //-------------------------------------------
alarmedlock = new(ReadersWritersLock); alarmedlock = new(ReadersWritersLock);
...@@ -399,6 +402,7 @@ void AlarmHandler::init_device() ...@@ -399,6 +402,7 @@ void AlarmHandler::init_device()
attr_alarmSummary_read = new Tango::DevString[10000]; attr_alarmSummary_read = new Tango::DevString[10000];
attr_eventList_read = new Tango::DevString[10000]; attr_eventList_read = new Tango::DevString[10000];
attr_eventSummary_read = new Tango::DevString[10000]; attr_eventSummary_read = new Tango::DevString[10000];
attr_alarmDisabled_read = new Tango::DevString[10000];
/*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandler::init_device) ENABLED START -----*/
/* for(size_t i=0; i<MAX_ALARMS; i++) /* for(size_t i=0; i<MAX_ALARMS; i++)
{ {
...@@ -412,6 +416,7 @@ void AlarmHandler::init_device() ...@@ -412,6 +416,7 @@ void AlarmHandler::init_device()
alarmSummary_read[i].resize(MAX_ATTR_SUMMARY); alarmSummary_read[i].resize(MAX_ATTR_SUMMARY);
}*/ }*/
// Initialize device // Initialize device
alarms.set_al_qual(setAlarmQuality);
alarms.set_err_delay(errorDelay); alarms.set_err_delay(errorDelay);
thread->period = subscribeRetryPeriod; thread->period = subscribeRetryPeriod;
...@@ -486,6 +491,8 @@ void AlarmHandler::init_device() ...@@ -486,6 +491,8 @@ void AlarmHandler::init_device()
rule_names[formula_grammar::val_qualityID] = "ValQuality"; rule_names[formula_grammar::val_qualityID] = "ValQuality";
rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus"; rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus";
rule_names[formula_grammar::propertyID] = "EventProperty"; rule_names[formula_grammar::propertyID] = "EventProperty";
rule_names[formula_grammar::index_rangeID] = "RangeIndex";
rule_names[formula_grammar::index_listID] = "ListIndex";
/* /*
* get device attribute properties and initialize internal * get device attribute properties and initialize internal
...@@ -520,7 +527,7 @@ void AlarmHandler::init_device() ...@@ -520,7 +527,7 @@ void AlarmHandler::init_device()
} catch(string & e) } catch(string & e)
{ {
ERROR_STREAM << "AlarmHandler::init_device(): " << e << endl; ERROR_STREAM << "AlarmHandler::init_device(): " << e << endl;
cout << "Error: " << e << ". Exiting..." << endl; TANGO_LOG << "Error: " << e << ". Exiting..." << endl;
exit(-4); exit(-4);
} }
...@@ -629,6 +636,8 @@ void AlarmHandler::init_device() ...@@ -629,6 +636,8 @@ void AlarmHandler::init_device()
for(alarm_container_t::iterator i = alarms.v_alarm.begin(); \ for(alarm_container_t::iterator i = alarms.v_alarm.begin(); \
i!=alarms.v_alarm.end(); i++) i!=alarms.v_alarm.end(); i++)
{ {
if(!i->second.enabled)
i->second.ts_time_silenced = gettime(); //TODO: save time when alarm was disabled
if(i->second.cmd_name_a.length() > 0) if(i->second.cmd_name_a.length() > 0)
{ {
try { try {
...@@ -748,7 +757,7 @@ void AlarmHandler::init_device() ...@@ -748,7 +757,7 @@ void AlarmHandler::init_device()
} }
} }
set_change_event("alarm",true,false); set_change_event("alarm",true,true);
/* /*
* create alarm processing thread * create alarm processing thread
*/ */
...@@ -821,6 +830,7 @@ void AlarmHandler::get_device_property() ...@@ -821,6 +830,7 @@ void AlarmHandler::get_device_property()
dev_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod")); dev_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
dev_prop.push_back(Tango::DbDatum("StatisticsTimeWindow")); dev_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
dev_prop.push_back(Tango::DbDatum("ErrorDelay")); dev_prop.push_back(Tango::DbDatum("ErrorDelay"));
dev_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// is there at least one property to be read ? // is there at least one property to be read ?
if (dev_prop.size()>0) if (dev_prop.size()>0)
...@@ -879,6 +889,17 @@ void AlarmHandler::get_device_property() ...@@ -879,6 +889,17 @@ void AlarmHandler::get_device_property()
// And try to extract ErrorDelay value from database // And try to extract ErrorDelay value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> errorDelay; if (dev_prop[i].is_empty()==false) dev_prop[i] >> errorDelay;
// Try to initialize SetAlarmQuality from class property
cl_prop = ds_class->get_class_property(dev_prop[++i].name);
if (cl_prop.is_empty()==false) cl_prop >> setAlarmQuality;
else {
// Try to initialize SetAlarmQuality from default device value
def_prop = ds_class->get_default_device_property(dev_prop[i].name);
if (def_prop.is_empty()==false) def_prop >> setAlarmQuality;
}
// And try to extract SetAlarmQuality value from database
if (dev_prop[i].is_empty()==false) dev_prop[i] >> setAlarmQuality;
} }
/*----- PROTECTED REGION ID(AlarmHandler::get_device_property_after) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandler::get_device_property_after) ENABLED START -----*/
...@@ -979,11 +1000,13 @@ void AlarmHandler::read_alarm(Tango::Attribute &attr) ...@@ -979,11 +1000,13 @@ void AlarmHandler::read_alarm(Tango::Attribute &attr)
//DEBUG_STREAM << "AlarmHandler::read_alarm(Tango::Attribute &attr) entering... " << endl; //DEBUG_STREAM << "AlarmHandler::read_alarm(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_alarm) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandler::read_alarm) ENABLED START -----*/
// Add your own code here // Add your own code here
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
attr.set_value(ds, ds_num, 0, false); attr.set_value(ds, ds_num, 0, false);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarm /*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarm
...@@ -1206,6 +1229,24 @@ void AlarmHandler::read_eventSummary(Tango::Attribute &attr) ...@@ -1206,6 +1229,24 @@ void AlarmHandler::read_eventSummary(Tango::Attribute &attr)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventSummary /*----- PROTECTED REGION END -----*/ // AlarmHandler::read_eventSummary
} }
//--------------------------------------------------------
/**
* Read attribute alarmDisabled related method
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
//--------------------------------------------------------
void AlarmHandler::read_alarmDisabled(Tango::Attribute &attr)
{
//DEBUG_STREAM << "AlarmHandler::read_alarmDisabled(Tango::Attribute &attr) entering... " << endl;
/*----- PROTECTED REGION ID(AlarmHandler::read_alarmDisabled) ENABLED START -----*/
// Set the attribute value
attr.set_value(attr_alarmDisabled_read, alarmDisabled_sz);
/*----- PROTECTED REGION END -----*/ // AlarmHandler::read_alarmDisabled
}
//-------------------------------------------------------- //--------------------------------------------------------
/** /**
...@@ -1234,7 +1275,10 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr) ...@@ -1234,7 +1275,10 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
break; break;
} }
} }
bool error; bool error=false;
bool enabled=true;
bool shelved=false;
int silenced=0;
if(it != alarms.v_alarm.end()) if(it != alarms.v_alarm.end())
{ {
reason = it->second.ex_reason; reason = it->second.ex_reason;
...@@ -1242,10 +1286,13 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr) ...@@ -1242,10 +1286,13 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin = it->second.ex_origin; origin = it->second.ex_origin;
quality = it->second.quality; quality = it->second.quality;
error = it->second.error; error = it->second.error;
enabled = it->second.enabled;
shelved = it->second.shelved;
silenced = it->second.silenced;
} }
DEBUG_STREAM << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl; DEBUG_STREAM << "AlarmHandler::read_AlarmState: " << attr.get_name() << " desc=" << desc << endl;
alarms.vlock->readerOut(); alarms.vlock->readerOut();
if(error) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used if(error && enabled && !(shelved && silenced >0)) //TODO: if needs to be considered err_delay also in single alarm attributes, error must be used
//if(desc.length() > 0) //if(desc.length() > 0)
{ {
Tango::Except::throw_exception( Tango::Except::throw_exception(
...@@ -1254,7 +1301,7 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr) ...@@ -1254,7 +1301,7 @@ void AlarmHandler::read_AlarmState(Tango::Attribute &attr)
origin, Tango::ERR); origin, Tango::ERR);
} }
// Set the attribute value // Set the attribute value
if(quality != Tango::ATTR_VALID) if(quality != Tango::ATTR_VALID && setAlarmQuality)
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
...@@ -1375,7 +1422,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1375,7 +1422,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
localalarmed = *found; //NOTE: copy before updating ack localalarmed = *found; //NOTE: copy before updating ack
localv_alarm = i->second; localv_alarm = i->second;
//update alarm ack in alarmed table
found->ack = ACK; found->ack = ACK;
alarmedlock->readerOut(); alarmedlock->readerOut();
alarms.vlock->readerOut(); alarms.vlock->readerOut();
...@@ -1397,12 +1444,20 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1397,12 +1444,20 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
*attr_value = _RTNUN; *attr_value = _RTNUN;
try try
{ //DevFailed for push events { //DevFailed for push events
if(localv_alarm.ex_reason.empty()) if(!localv_alarm.error || !localv_alarm.enabled || (localv_alarm.shelved && localv_alarm.silenced > 0))
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false); if(setAlarmQuality)
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false); {
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)localv_alarm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(localv_alarm.attr_name,(Tango::DevEnum *)attr_value);
}
} }
else else
{ {
...@@ -1454,6 +1509,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1454,6 +1509,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -1462,6 +1518,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1462,6 +1518,7 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -1476,7 +1533,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1476,7 +1533,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -1487,7 +1545,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin) ...@@ -1487,7 +1545,8 @@ void AlarmHandler::ack(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0],alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
...@@ -1690,7 +1749,7 @@ void AlarmHandler::load(Tango::DevString argin) ...@@ -1690,7 +1749,7 @@ void AlarmHandler::load(Tango::DevString argin)
alarms.vlock->readerOut(); alarms.vlock->readerOut();
#if 0//TODO #if 1//TODO
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
...@@ -1778,6 +1837,7 @@ void AlarmHandler::remove(Tango::DevString argin) ...@@ -1778,6 +1837,7 @@ void AlarmHandler::remove(Tango::DevString argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -1786,6 +1846,7 @@ void AlarmHandler::remove(Tango::DevString argin) ...@@ -1786,6 +1846,7 @@ void AlarmHandler::remove(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -1800,7 +1861,8 @@ void AlarmHandler::remove(Tango::DevString argin) ...@@ -1800,7 +1861,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -1811,7 +1873,8 @@ void AlarmHandler::remove(Tango::DevString argin) ...@@ -1811,7 +1873,8 @@ void AlarmHandler::remove(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -1862,13 +1925,13 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin) ...@@ -1862,13 +1925,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 += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}*/ }*/
start_pos = filter.find("*", start_pos); 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.replace(start_pos, 1, "");
filter_begin = filter; filter_begin = filter;
DEBUG_STREAM << __func__ << ": updated filter to: " << filter_begin; 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_begin=filter.substr(0,start_pos);
string filter_end=filter.substr(start_pos+1); string filter_end=filter.substr(start_pos+1);
...@@ -1896,9 +1959,9 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin) ...@@ -1896,9 +1959,9 @@ Tango::DevVarStringArray *AlarmHandler::search_alarm(Tango::DevString argin)
{ {
ostringstream os; ostringstream os;
os.clear(); os.clear();
os << ai->second.ts.tv_sec << SEP << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay << os << KEY(NAME_KEY) << ai->second.name << SEP << KEY(FORMULA_KEY) << ai->second.formula << SEP << KEY(ONDELAY_KEY) << ai->second.on_delay << SEP << KEY(OFFDELAY_KEY) << ai->second.off_delay <<
SEP << KEY(LEVEL_KEY) << ai->second.lev << SEP << KEY(SILENT_TIME_KEY) << ai->second.silent_time << SEP << KEY(GROUP_KEY) << ai->second.grp2str() << SEP << KEY(MESSAGE_KEY) << ai->second.msg << SEP << KEY(URL_KEY) << ai->second.url << SEP << KEY(LEVEL_KEY) << ai->second.lev << SEP << KEY(SILENT_TIME_KEY) << ai->second.silent_time << SEP << KEY(GROUP_KEY) << ai->second.grp2str() << SEP << KEY(MESSAGE_KEY) << ai->second.msg << SEP << KEY(URL_KEY) << ai->second.url <<
SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0"); SEP << KEY(ON_COMMAND_KEY) << ai->second.cmd_name_a << SEP << KEY(OFF_COMMAND_KEY) << ai->second.cmd_name_n << SEP << KEY(RECEIVERS_KEY) << ai->second.receivers << SEP << KEY(ENABLED_KEY) << (ai->second.enabled ? "1" : "0");
alarm_filtered.push_back(os.str()); alarm_filtered.push_back(os.str());
} }
} /* for */ } /* for */
...@@ -1939,6 +2002,7 @@ void AlarmHandler::stop_audible() ...@@ -1939,6 +2002,7 @@ void AlarmHandler::stop_audible()
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -1947,6 +2011,7 @@ void AlarmHandler::stop_audible() ...@@ -1947,6 +2011,7 @@ void AlarmHandler::stop_audible()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -1961,7 +2026,8 @@ void AlarmHandler::stop_audible() ...@@ -1961,7 +2026,8 @@ void AlarmHandler::stop_audible()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -1972,7 +2038,8 @@ void AlarmHandler::stop_audible() ...@@ -1972,7 +2038,8 @@ void AlarmHandler::stop_audible()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2006,6 +2073,16 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2006,6 +2073,16 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
alarm_container_t::iterator i = alarms.v_alarm.find(*si); alarm_container_t::iterator i = alarms.v_alarm.find(*si);
if(i != alarms.v_alarm.end()) if(i != alarms.v_alarm.end())
{ {
if(!i->second.enabled)
{
ostringstream err;
err << *si << " is not enabled";
alarms.vlock->readerOut();
Tango::Except::throw_exception( \
(const char*)"NOT_ENABLED", \
(const char*)err.str().c_str(), \
(const char*)__func__, Tango::ERR);
}
if(i->second.silenced > 0) if(i->second.silenced > 0)
{ {
Tango::TimeVal now = gettime(); Tango::TimeVal now = gettime();
...@@ -2077,6 +2154,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2077,6 +2154,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2085,6 +2163,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2085,6 +2163,7 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2099,7 +2178,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2099,7 +2178,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2110,7 +2190,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2110,7 +2190,8 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2120,7 +2201,6 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin) ...@@ -2120,7 +2201,6 @@ void AlarmHandler::silence(const Tango::DevVarStringArray *argin)
/*----- PROTECTED REGION END -----*/ // AlarmHandler::silence /*----- PROTECTED REGION END -----*/ // AlarmHandler::silence
} }
//-------------------------------------------------------- //--------------------------------------------------------
/** /**
* Command Modify related method * Command Modify related method
...@@ -2179,6 +2259,7 @@ void AlarmHandler::modify(Tango::DevString argin) ...@@ -2179,6 +2259,7 @@ void AlarmHandler::modify(Tango::DevString argin)
i->second.cmd_dp_n = alm.cmd_dp_n; i->second.cmd_dp_n = alm.cmd_dp_n;
i->second.cmd_action_n = alm.cmd_action_n; i->second.cmd_action_n = alm.cmd_action_n;
//i->second.send_arg_n = alm.send_arg_n; //i->second.send_arg_n = alm.send_arg_n;
i->second.receivers = alm.receivers;
i->second.enabled = alm.enabled; i->second.enabled = alm.enabled;
//update attribute properties //update attribute properties
...@@ -2276,10 +2357,11 @@ void AlarmHandler::modify(Tango::DevString argin) ...@@ -2276,10 +2357,11 @@ void AlarmHandler::modify(Tango::DevString argin)
//4: load modified alarm //4: load modified alarm
//------------------------------ //------------------------------
load(argin); load(argin);
usleep(150000);//wait some time before updating attributes with prepare_alarm_attr so that event are subscribed and first evaluation done
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2288,6 +2370,7 @@ void AlarmHandler::modify(Tango::DevString argin) ...@@ -2288,6 +2370,7 @@ void AlarmHandler::modify(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2302,7 +2385,8 @@ void AlarmHandler::modify(Tango::DevString argin) ...@@ -2302,7 +2385,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2313,7 +2397,8 @@ void AlarmHandler::modify(Tango::DevString argin) ...@@ -2313,7 +2397,8 @@ void AlarmHandler::modify(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2436,13 +2521,24 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2436,13 +2521,24 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
*attr_value = _SHLVD; *attr_value = _SHLVD;
try try
{ //DevFailed for push events { //DevFailed for push events
if(alm.ex_reason.empty()) #if 0//do not store errors for disabled alarms
if(!alm.error)
#endif
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); if(setAlarmQuality)
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); {
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
} }
#if 0//do not store errors for disabled alarms
else else
{ {
Tango::DevErrorList errors(1); Tango::DevErrorList errors(1);
...@@ -2455,6 +2551,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2455,6 +2551,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event(alm.attr_name, &except); push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except); push_archive_event(alm.attr_name, &except);
} }
#endif
} catch(Tango::DevFailed & ex) } catch(Tango::DevFailed & ex)
{ {
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
...@@ -2465,6 +2562,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2465,6 +2562,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2473,6 +2571,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2473,6 +2571,7 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2485,7 +2584,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2485,7 +2584,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz); push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz); push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2494,7 +2594,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin) ...@@ -2494,7 +2594,8 @@ void AlarmHandler::shelve(const Tango::DevVarStringArray *argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz); push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz); push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2551,12 +2652,20 @@ void AlarmHandler::enable(Tango::DevString argin) ...@@ -2551,12 +2652,20 @@ void AlarmHandler::enable(Tango::DevString argin)
*attr_value = _RTNUN; *attr_value = _RTNUN;
try try
{ //DevFailed for push events { //DevFailed for push events
if(alm.ex_reason.empty()) if(!alm.error)
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); if(setAlarmQuality)
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); {
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
} }
else else
{ {
...@@ -2578,6 +2687,7 @@ void AlarmHandler::enable(Tango::DevString argin) ...@@ -2578,6 +2687,7 @@ void AlarmHandler::enable(Tango::DevString argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2586,6 +2696,7 @@ void AlarmHandler::enable(Tango::DevString argin) ...@@ -2586,6 +2696,7 @@ void AlarmHandler::enable(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2598,7 +2709,8 @@ void AlarmHandler::enable(Tango::DevString argin) ...@@ -2598,7 +2709,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz); push_change_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz); push_change_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2607,7 +2719,8 @@ void AlarmHandler::enable(Tango::DevString argin) ...@@ -2607,7 +2719,8 @@ void AlarmHandler::enable(Tango::DevString argin)
push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz); push_archive_event("alarmOutOfService",&attr_alarmOutOfService_read[0], outOfServiceAlarms_sz);
push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz); push_archive_event("alarmSilenced",&attr_alarmSilenced_read[0], silencedAlarms_sz);
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2649,6 +2762,7 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2649,6 +2762,7 @@ void AlarmHandler::disable(Tango::DevString argin)
i->second.enabled = false; i->second.enabled = false;
i->second.ts_time_silenced = gettime();
i->second.silenced = (i->second.silent_time > 0) ? 0 : -1; //0: can be silenced, -1: cannot be silenced i->second.silenced = (i->second.silent_time > 0) ? 0 : -1; //0: can be silenced, -1: cannot be silenced
i->second.shelved = false; i->second.shelved = false;
alarm_t alm = i->second; alarm_t alm = i->second;
...@@ -2658,13 +2772,24 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2658,13 +2772,24 @@ void AlarmHandler::disable(Tango::DevString argin)
*attr_value = _OOSRV; *attr_value = _OOSRV;
try try
{ //DevFailed for push events { //DevFailed for push events
if(alm.ex_reason.empty()) #if 0 //do not store errors for disabled alarms
if(!alm.error)
#endif
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); if(setAlarmQuality)
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false); {
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)alm.quality, 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
} }
#if 0 //do not store errors for disabled alarms
else else
{ {
Tango::DevErrorList errors(1); Tango::DevErrorList errors(1);
...@@ -2677,6 +2802,7 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2677,6 +2802,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event(alm.attr_name, &except); push_change_event(alm.attr_name, &except);
push_archive_event(alm.attr_name, &except); push_archive_event(alm.attr_name, &except);
} }
#endif
} catch(Tango::DevFailed & ex) } catch(Tango::DevFailed & ex)
{ {
WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
...@@ -2703,6 +2829,7 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2703,6 +2829,7 @@ void AlarmHandler::disable(Tango::DevString argin)
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2711,6 +2838,7 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2711,6 +2838,7 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2725,7 +2853,8 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2725,7 +2853,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2736,7 +2865,8 @@ void AlarmHandler::disable(Tango::DevString argin) ...@@ -2736,7 +2865,8 @@ void AlarmHandler::disable(Tango::DevString argin)
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2797,6 +2927,7 @@ void AlarmHandler::stop_new() ...@@ -2797,6 +2927,7 @@ void AlarmHandler::stop_new()
prepare_alarm_attr(); prepare_alarm_attr();
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -2805,6 +2936,7 @@ void AlarmHandler::stop_new() ...@@ -2805,6 +2936,7 @@ void AlarmHandler::stop_new()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -2819,7 +2951,8 @@ void AlarmHandler::stop_new() ...@@ -2819,7 +2951,8 @@ void AlarmHandler::stop_new()
push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_change_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read); push_change_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_change_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -2830,7 +2963,8 @@ void AlarmHandler::stop_new() ...@@ -2830,7 +2963,8 @@ void AlarmHandler::stop_new()
push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz); push_archive_event("alarmList",&attr_alarmList_read[0], listAlarms_sz);
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read); push_archive_event("alarmSummary",&attr_alarmSummary_read[0],alarmSummary_sz);
push_archive_event("alarmDisabled",&attr_alarmDisabled_read[0], alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -2897,11 +3031,23 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString ...@@ -2897,11 +3031,23 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
ostringstream tmp_ex; ostringstream tmp_ex;
tmp_ex.str(""); tmp_ex.str("");
ostringstream tmp;
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
if(it->second.error) if(it->second.error)
{ {
tmp_ex << "{\"Reason\":\"" << it->second.ex_reason << "\",\"Desc\":\"" << it->second.ex_desc << "\",\"Origin\":\"" << it->second.ex_origin << "\"}"; tmp_ex << "{\"Reason\":\"" << it->second.ex_reason << "\",\"Desc\":\"" << it->second.ex_desc << "\",\"Origin\":\"" << it->second.ex_origin << "\"}";
info.insert(make_pair(VALUE_KEY,string("ERROR"))); string almstate(tmp_val.str());
complete.push_back(KEY(VALUE_KEY)+string("ERROR")); if(almstate != "SHLVD" && almstate != "OOSRV")
{
almstate = S_ERROR;
}
info.insert(make_pair(VALUE_KEY,almstate));
complete.push_back(KEY(VALUE_KEY)+almstate);
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula)); info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula); complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,tmp_ex.str())); info.insert(make_pair(ATTR_VALUES_KEY,tmp_ex.str()));
...@@ -2911,13 +3057,26 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString ...@@ -2911,13 +3057,26 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
{ {
info.insert(make_pair(VALUE_KEY,tmp_val.str())); info.insert(make_pair(VALUE_KEY,tmp_val.str()));
complete.push_back(KEY(VALUE_KEY)+tmp_val.str()); complete.push_back(KEY(VALUE_KEY)+tmp_val.str());
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(FORMULA_KEY,it->second.formula)); info.insert(make_pair(FORMULA_KEY,it->second.formula));
complete.push_back(KEY(FORMULA_KEY)+it->second.formula); complete.push_back(KEY(FORMULA_KEY)+it->second.formula);
info.insert(make_pair(ATTR_VALUES_KEY,it->second.attr_values)); info.insert(make_pair(ATTR_VALUES_KEY,it->second.attr_values));
complete.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values); complete.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values);
} }
tm time_tm;
time_t time_sec= it->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
ostringstream time_s;
time_s << time_buf << "." << it->second.ts.tv_usec;
info.insert(make_pair(ALARM_TIME_KEY,time_s.str()));
complete.push_back(KEY(ALARM_TIME_KEY)+time_s.str());
ostringstream tmp_qual; ostringstream tmp_qual;
try try
...@@ -2929,7 +3088,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString ...@@ -2929,7 +3088,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
} }
info.insert(make_pair(QUALITY_KEY,tmp_qual.str())); info.insert(make_pair(QUALITY_KEY,tmp_qual.str()));
complete.push_back(KEY(QUALITY_KEY)+tmp_qual.str()); complete.push_back(KEY(QUALITY_KEY)+tmp_qual.str());
ostringstream tmp;
//#if 0 //#if 0
tmp.str(""); tmp.str("");
tmp << (it->second.enabled ? "1" : "0"); tmp << (it->second.enabled ? "1" : "0");
...@@ -2944,6 +3103,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString ...@@ -2944,6 +3103,7 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
info.insert(make_pair(ACKNOWLEDGED_KEY,tmp.str())); //TODO: redundant, information already in attr_value info.insert(make_pair(ACKNOWLEDGED_KEY,tmp.str())); //TODO: redundant, information already in attr_value
complete.push_back(KEY(ACKNOWLEDGED_KEY)+tmp.str()); //TODO: redundant, information already in attr_value complete.push_back(KEY(ACKNOWLEDGED_KEY)+tmp.str()); //TODO: redundant, information already in attr_value
//#endif //#endif
tmp.str(""); tmp.str("");
tmp << (it->second.is_new ? "1" : "0"); tmp << (it->second.is_new ? "1" : "0");
info.insert(make_pair(AUDIBLE_KEY,tmp.str())); info.insert(make_pair(AUDIBLE_KEY,tmp.str()));
...@@ -2984,17 +3144,12 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString ...@@ -2984,17 +3144,12 @@ Tango::DevVarStringArray *AlarmHandler::get_alarm_info(const Tango::DevVarString
complete.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str()); complete.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str());
info.insert(make_pair(GROUP_KEY,it->second.grp2str())); info.insert(make_pair(GROUP_KEY,it->second.grp2str()));
complete.push_back(KEY(GROUP_KEY)+it->second.grp2str()); complete.push_back(KEY(GROUP_KEY)+it->second.grp2str());
tmp.str("");
tmp << "\"" << it->second.msg << "\"";
info.insert(make_pair(MESSAGE_KEY,tmp.str()));
complete.push_back(KEY(MESSAGE_KEY)+tmp.str());
info.insert(make_pair(URL_KEY,it->second.url));
complete.push_back(KEY(URL_KEY)+it->second.url);
info.insert(make_pair(ON_COMMAND_KEY,it->second.cmd_name_a)); info.insert(make_pair(ON_COMMAND_KEY,it->second.cmd_name_a));
complete.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a); complete.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a);
info.insert(make_pair(OFF_COMMAND_KEY,it->second.cmd_name_n)); info.insert(make_pair(OFF_COMMAND_KEY,it->second.cmd_name_n));
complete.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n); complete.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n);
info.insert(make_pair(RECEIVERS_KEY,it->second.receivers));
complete.push_back(KEY(RECEIVERS_KEY)+it->second.receivers);
alarms.vlock->readerOut(); alarms.vlock->readerOut();
argout = new Tango::DevVarStringArray(); argout = new Tango::DevVarStringArray();
if(argin->length() == 1) if(argin->length() == 1)
...@@ -3124,6 +3279,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string> ...@@ -3124,6 +3279,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
alm.send_arg_n = false; alm.send_arg_n = false;
alm.dp_n = NULL; alm.dp_n = NULL;
alm.enabled = 1; alm.enabled = 1;
alm.receivers.clear();
evn.clear(); evn.clear();
alm.formula_tree = alm.formula_tree =
...@@ -3144,6 +3300,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string> ...@@ -3144,6 +3300,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";" alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";" alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0) if(alm.cmd_name_a.length() > 0)
{ {
const char *c = alm.cmd_name_a.c_str(); const char *c = alm.cmd_name_a.c_str();
...@@ -3208,6 +3365,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string> ...@@ -3208,6 +3365,7 @@ void AlarmHandler::load_alarm(string alarm_string, alarm_t &alm, vector<string>
DEBUG_STREAM << " lev = '" << alm.lev << "'" << endl; DEBUG_STREAM << " lev = '" << alm.lev << "'" << endl;
DEBUG_STREAM << " action_a = '" << alm.cmd_name_a << "'" << endl; DEBUG_STREAM << " action_a = '" << alm.cmd_name_a << "'" << endl;
DEBUG_STREAM << " action_n = '" << alm.cmd_name_n << "'" << endl; DEBUG_STREAM << " action_n = '" << alm.cmd_name_n << "'" << endl;
DEBUG_STREAM << " receivers = '" << alm.receivers << "'" << endl;
DEBUG_STREAM << " enabled = '" << (alm.enabled ? "1" : "0") << "'" << endl; DEBUG_STREAM << " enabled = '" << (alm.enabled ? "1" : "0") << "'" << endl;
if ((alm.name.empty() == false) && \ if ((alm.name.empty() == false) && \
(alm.formula.empty() == false) && \ (alm.formula.empty() == false) && \
...@@ -3294,7 +3452,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting) ...@@ -3294,7 +3452,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
{ {
alarms.push_back(a); //take and release writer vlock alarms.push_back(a); //take and release writer vlock
DEBUG_STREAM << "AlarmHandler::add_alarm(): added alarm '" \ DEBUG_STREAM << "AlarmHandler::add_alarm(): added alarm '" \
<< a.name << "'" << endl; << a.name << "' starting=" << (int)starting << endl;
if(!starting) if(!starting)
{ {
alarms.vlock->readerIn(); alarms.vlock->readerIn();
...@@ -3314,7 +3472,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting) ...@@ -3314,7 +3472,7 @@ void AlarmHandler::add_alarm(alarm_t& a, bool starting)
} }
} }
void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&) void AlarmHandler::add_event(alarm_t& a, vector<string> &evn)
{ {
DEBUG_STREAM << "AlarmHandler::add_event(): formula '" << a.formula << "' found " << evn.size() << " events" << endl; DEBUG_STREAM << "AlarmHandler::add_event(): formula '" << a.formula << "' found " << evn.size() << " events" << endl;
/* /*
...@@ -3430,6 +3588,7 @@ void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&) ...@@ -3430,6 +3588,7 @@ void AlarmHandler::add_event(alarm_t& a, vector<string> &evn) throw(string&)
} }
} }
} //for (vector<string>::iterator j = evn.begin(); ... } //for (vector<string>::iterator j = evn.begin(); ...
thread->signal(); //wake up subscibe thread if not waked by events->add
for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++) for(vector<string>::iterator j = evn.begin(); j != evn.end(); j++)
{ {
...@@ -3456,7 +3615,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3456,7 +3615,7 @@ void AlarmHandler::do_alarm(bei_t& e)
{ {
ostringstream o; ostringstream o;
o << e.msg; o << e.msg;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": " << e.ev_name << ": " << o.str() << endl;
events->veclock.readerIn(); events->veclock.readerIn();
vector<event>::iterator found_ev = \ vector<event>::iterator found_ev = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name); find(events->v_event.begin(), events->v_event.end(), e.ev_name);
...@@ -3501,6 +3660,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3501,6 +3660,7 @@ void AlarmHandler::do_alarm(bei_t& e)
} }
if(found_ev != events->v_event.end()) if(found_ev != events->v_event.end())
{ {
found_ev->valid = false;
Tango::TimeVal ts = gettime(); Tango::TimeVal ts = gettime();
found_ev->err_counter++; found_ev->err_counter++;
if(e.type == TYPE_TANGO_ERR) if(e.type == TYPE_TANGO_ERR)
...@@ -3519,15 +3679,19 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3519,15 +3679,19 @@ void AlarmHandler::do_alarm(bei_t& e)
list<string>::iterator j = m_alarm.begin(); list<string>::iterator j = m_alarm.begin();
while (j != m_alarm.end()) 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(); alarms.vlock->readerIn();
alarm_container_t::iterator it = alarms.v_alarm.find(*j); alarm_container_t::iterator it = alarms.v_alarm.find(*j);
if(it != alarms.v_alarm.end()) if(it != alarms.v_alarm.end())
{ {
#if 0 //already done in alarm_table::update called by do_alarm_eval
it->second.err_counter++; it->second.err_counter++;
//if first error, reset ACK //if first error, reset ACK
if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty()) if(it->second.ex_reason.empty() && it->second.ex_desc.empty() && it->second.ex_origin.empty())
{ {
it->second.ack = NOT_ACK;
it->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay it->second.ts_err_delay = gettime(); //first occurrance of this error, now begin to wait for err delay
} }
if(e.type == TYPE_TANGO_ERR) if(e.type == TYPE_TANGO_ERR)
...@@ -3541,32 +3705,69 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3541,32 +3705,69 @@ void AlarmHandler::do_alarm(bei_t& e)
if((ts.tv_sec - errorDelay) > it->second.ts_err_delay.tv_sec) //error is present and err delay has passed if((ts.tv_sec - errorDelay) > it->second.ts_err_delay.tv_sec) //error is present and err delay has passed
{ {
if(!it->second.error) if(!it->second.error)
{
it->second.is_new = 1; it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true; it->second.error = true;
} }
} }
else else
{ {
if(!it->second.error) if(!it->second.error)
{
it->second.is_new = 1; it->second.is_new = 1;
it->second.ack = NOT_ACK;//if first error, reset ACK
}
it->second.error = true; it->second.error = true;
} }
#endif
alarm_t alm = it->second; alarm_t alm = it->second;
alarms.vlock->readerOut(); alarms.vlock->readerOut();
try 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))
{ {
Tango::DevErrorList errors(1); try
errors.length(1); {
errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str()); Tango::DevErrorList errors(1);
errors[0].severity = Tango::ERR; errors.length(1);
errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str()); errors[0].desc = CORBA::string_dup(alm.ex_desc.c_str());
errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str()); errors[0].severity = Tango::ERR;
Tango::DevFailed except(errors); errors[0].reason = CORBA::string_dup(alm.ex_reason.c_str());
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl; errors[0].origin = CORBA::string_dup(alm.ex_origin.c_str());
push_change_event(alm.attr_name, &except); Tango::DevFailed except(errors);
push_archive_event(alm.attr_name, &except); DEBUG_STREAM << "AlarmHandler::"<<__func__<<": PUSHING EXCEPTION FOR " << alm.attr_name << " " << alm.ex_desc << "-" << alm.ex_reason << "-" << alm.ex_origin << endl;
}catch(Tango::DevFailed &ex) push_change_event(alm.attr_name, &except);
{} push_archive_event(alm.attr_name, &except);
}catch(Tango::DevFailed &ex)
{}
}
else if(alm.error) //TODO: or if(changed) ?
{
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name);
if(!alm.enabled)
{
*attr_value = _OOSRV;
}
else if(alm.shelved && alm.silenced > 0)
{
*attr_value = _SHLVD;
}
if(setAlarmQuality)
{
timeval now;
gettimeofday(&now, NULL);
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value,now,static_cast<Tango::AttrQuality>(alm.quality), 1/*size*/, 0, false);
}
else
{
push_change_event(alm.attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(alm.attr_name,(Tango::DevEnum *)attr_value);
}
}
#endif
} }
else else
{ {
...@@ -3575,6 +3776,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3575,6 +3776,7 @@ void AlarmHandler::do_alarm(bei_t& e)
j++; j++;
} }
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -3583,6 +3785,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3583,6 +3785,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -3598,6 +3801,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3598,6 +3801,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -3609,11 +3813,16 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3609,11 +3813,16 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
}
else
{
events->veclock.readerOut();
} }
return; return;
} }
//here not event error
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl; DEBUG_STREAM << "AlarmHandler::"<<__func__<<": arrived event=" << e.ev_name << endl;
formula_res_t res;
events->veclock.readerIn(); events->veclock.readerIn();
vector<event>::iterator found = \ vector<event>::iterator found = \
find(events->v_event.begin(), events->v_event.end(), e.ev_name); find(events->v_event.begin(), events->v_event.end(), e.ev_name);
...@@ -3657,9 +3866,12 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3657,9 +3866,12 @@ void AlarmHandler::do_alarm(bei_t& e)
} }
} }
if (found != events->v_event.end()) if (found != events->v_event.end())
{ {
found->value = e.value; found->value = e.value;
found->value_string = e.value_string; found->value_string = e.value_string;
found->read_size = e.read_size;
found->dim_x = e.dim_x;
found->dim_y = e.dim_y;
found->quality = e.quality; found->quality = e.quality;
//found->errors = e.errors; //found->errors = e.errors;
found->ex_reason = e.ex_reason; found->ex_reason = e.ex_reason;
...@@ -3701,6 +3913,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3701,6 +3913,7 @@ void AlarmHandler::do_alarm(bei_t& e)
return; return;
} }
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -3709,6 +3922,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3709,6 +3922,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -3724,6 +3938,7 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3724,6 +3938,7 @@ void AlarmHandler::do_alarm(bei_t& e)
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -3735,9 +3950,11 @@ void AlarmHandler::do_alarm(bei_t& e) ...@@ -3735,9 +3950,11 @@ void AlarmHandler::do_alarm(bei_t& e)
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
} }
else else
{ {
events->veclock.readerOut();
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl; DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
} }
} /* do_alarm() */ } /* do_alarm() */
...@@ -3777,10 +3994,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3777,10 +3994,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
it->second.to_be_evaluated = false; it->second.to_be_evaluated = false;
it->second.attr_values.erase(it->second.attr_values.size()-1); it->second.attr_values.erase(it->second.attr_values.size()-1);
it->second.attr_values += string("}"); 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=" << print_array(res.value,res.dim_x,res.dim_y) << " 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 = 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; changed = changed || (prev_error && res.valid);
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << endl; DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name); Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
if(!it->second.enabled) if(!it->second.enabled)
*attr_value = _OOSRV; *attr_value = _OOSRV;
...@@ -3801,12 +4018,20 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3801,12 +4018,20 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
try try
{ //DevFailed for push events { //DevFailed for push events
if(!it->second.error) if(!it->second.error || !it->second.enabled || (it->second.shelved && it->second.silenced > 0))
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false); if(setAlarmQuality)
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false); {
push_change_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value,now,quality, 1/*size*/, 0, false);
}
else
{
push_change_event(attr_name,(Tango::DevEnum *)attr_value);
push_archive_event(attr_name,(Tango::DevEnum *)attr_value);
}
} }
else else
{ {
...@@ -3826,7 +4051,8 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3826,7 +4051,8 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
} }
} catch(std::out_of_range& ex) } catch(std::out_of_range& ex)
{ {
changed = !prev_error; events->veclock.readerOut(); //readerIn called in eval_expression
changed = true;//force update attributes in case of modify/load alarm with out_of_range exception
it->second.to_be_evaluated = true; it->second.to_be_evaluated = true;
ostringstream o; ostringstream o;
o << tmpname << ": in formula array index out of range!"; o << tmpname << ": in formula array index out of range!";
...@@ -3837,16 +4063,29 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3837,16 +4063,29 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1); Tango::DevErrorList errors(1);
errors.length(1); errors.length(1);
it->second.ex_reason = string("OUT_OF_RANGE"); it->second.ex_reason = string("OUT_OF_RANGE");
it->second.ex_desc = ev_name + ": " + o.str(); it->second.ex_desc = o.str();
it->second.ex_origin = ev_name; it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str()); errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR; errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str()); errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str()); errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors); Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except); if(enabled && !(shelved && silenced >0))
push_archive_event(attr_name, &except); {
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex) } catch(Tango::DevFailed & ex)
{ {
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
...@@ -3856,7 +4095,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3856,7 +4095,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
changed = !prev_error; changed = !prev_error;
it->second.to_be_evaluated = true; it->second.to_be_evaluated = true;
ostringstream o; ostringstream o;
o << tmpname << ": in formula err=" << ex; o << ex;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str()); set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try try
...@@ -3864,16 +4103,70 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3864,16 +4103,70 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
Tango::DevErrorList errors(1); Tango::DevErrorList errors(1);
errors.length(1); errors.length(1);
it->second.ex_reason = string("FORMULA_ERROR"); it->second.ex_reason = string("FORMULA_ERROR");
it->second.ex_desc = ev_name + ": " + o.str(); it->second.ex_desc = o.str();
it->second.ex_origin = ev_name; it->second.ex_origin = ev_name;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str()); errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR; errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str()); errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str()); errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors); Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
push_change_event(attr_name, &except); if(enabled && !(shelved && silenced >0))
push_archive_event(attr_name, &except); {
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex)
{
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
}
}
catch(Tango::DevFailed & ex)
{
changed = !prev_error;
it->second.to_be_evaluated = true;
ostringstream o;
o << ex.errors[0].desc;
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << o.str() << endl;
set_internal_alarm(INTERNAL_ERROR, gettime(), o.str());
try
{ //DevFailed for push events
Tango::DevErrorList errors(1);
errors.length(1);
it->second.ex_reason = ex.errors[0].reason;
it->second.ex_desc = ex.errors[0].desc;
it->second.ex_origin = ex.errors[0].origin;
errors[0].desc = CORBA::string_dup(it->second.ex_desc.c_str());
errors[0].severity = Tango::ERR;
errors[0].reason = CORBA::string_dup(it->second.ex_reason.c_str());
errors[0].origin = CORBA::string_dup(it->second.ex_origin.c_str());
Tango::DevFailed except(errors);
bool enabled=it->second.enabled;
bool shelved=it->second.shelved;
int silenced=it->second.silenced;
Tango::DevEnum *attr_value = get_AlarmState_data_ptr(attr_name);
it->second.error=true;
it->second.quality = Tango::ATTR_INVALID;
if(enabled && !(shelved && silenced >0))
{
*attr_value = _ERROR;
}
alarms.vlock->readerOut(); //Don't hold alarms lock while pushing events to prevent deadlocks
if(enabled && !(shelved && silenced >0))
{
push_change_event(attr_name, &except);
push_archive_event(attr_name, &except);
}
} catch(Tango::DevFailed & ex) } catch(Tango::DevFailed & ex)
{ {
WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl; WARN_STREAM << "AlarmHandler::"<<__func__<<": " << attr_name << " - EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
...@@ -3882,6 +4175,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ...@@ -3882,6 +4175,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
} }
else else
{ {
alarms.vlock->readerOut();
ostringstream o; ostringstream o;
//o << j->first << ": not found formula in alarm table" << ends; //o << j->first << ": not found formula in alarm table" << ends;
o << (alm_name) << ": not found formula in alarm table"; o << (alm_name) << ": not found formula in alarm table";
...@@ -3942,9 +4236,11 @@ void AlarmHandler::timer_update() ...@@ -3942,9 +4236,11 @@ void AlarmHandler::timer_update()
{ {
return; return;
} }
DEBUG_STREAM << "AlarmHandler::timer_update(): changed -> prepare_alarm_attr" << endl;
prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway prepare_alarm_attr();//TODO: frequencyAlarm should be updated anyway
try try
{ {
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false); //attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
...@@ -3953,6 +4249,7 @@ void AlarmHandler::timer_update() ...@@ -3953,6 +4249,7 @@ void AlarmHandler::timer_update()
push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false); push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
} }
else else
#endif
{ {
//attr.set_value(ds, ds_num, 0, false); //attr.set_value(ds, ds_num, 0, false);
push_change_event("alarm",ds, ds_num, 0, false); push_change_event("alarm",ds, ds_num, 0, false);
...@@ -3968,6 +4265,7 @@ void AlarmHandler::timer_update() ...@@ -3968,6 +4265,7 @@ void AlarmHandler::timer_update()
push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_change_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_change_event("alarmAudible",attr_alarmAudible_read); push_change_event("alarmAudible",attr_alarmAudible_read);
push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_change_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_change_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz); push_archive_event("alarmNormal",&attr_alarmNormal_read[0], normalAlarms_sz);
push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz); push_archive_event("alarmUnacknowledged",&attr_alarmUnacknowledged_read[0], unacknowledgedAlarms_sz);
push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz); push_archive_event("alarmAcknowledged",&attr_alarmAcknowledged_read[0], acknowledgedAlarms_sz);
...@@ -3979,6 +4277,7 @@ void AlarmHandler::timer_update() ...@@ -3979,6 +4277,7 @@ void AlarmHandler::timer_update()
push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz); push_archive_event("alarmFrequency",&attr_alarmFrequency_read[0], listAlarms_sz);
push_archive_event("alarmAudible",attr_alarmAudible_read); push_archive_event("alarmAudible",attr_alarmAudible_read);
push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz); push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
} catch(Tango::DevFailed& e) } catch(Tango::DevFailed& e)
{ {
ostringstream err; ostringstream err;
...@@ -3987,7 +4286,7 @@ void AlarmHandler::timer_update() ...@@ -3987,7 +4286,7 @@ void AlarmHandler::timer_update()
} }
} }
bool AlarmHandler::remove_alarm(string& s) throw(string&) bool AlarmHandler::remove_alarm(string& s)
{ {
DEBUG_STREAM << "AlarmHandler::"<<__func__<<": entering alm name=" << s << endl; DEBUG_STREAM << "AlarmHandler::"<<__func__<<": entering alm name=" << s << endl;
alarms.vlock->writerIn(); alarms.vlock->writerIn();
...@@ -4097,7 +4396,7 @@ bool AlarmHandler::remove_alarm(string& s) throw(string&) ...@@ -4097,7 +4396,7 @@ bool AlarmHandler::remove_alarm(string& s) throw(string&)
} /* remove_alarm() */ } /* remove_alarm() */
/*void AlarmHandler::add_to_database(alarm_t& a) throw(string&) /*void AlarmHandler::add_to_database(alarm_t& a)
{ {
Tango::DbDatum alarm("alarm"); Tango::DbDatum alarm("alarm");
Tango::DbData db_data; Tango::DbData db_data;
...@@ -4222,14 +4521,59 @@ void AlarmHandler::set_internal_alarm(string name, Tango::TimeVal t, string msg, ...@@ -4222,14 +4521,59 @@ 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) 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);
res.extract_result(); //from Array res.value to Scalar res.value
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << __func__ << ": finally value=" << print_array(res.value,res.dim_x,res.dim_y) << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"' quality=" << res.quality << endl;
#endif
if(res.valid)
{
res.ex_reason.clear();
res.ex_desc.clear();
res.ex_origin.clear();
res.error.clear();
}
return res;
}
void AlarmHandler::eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind)
{
if(i->value.id() == formula_grammar::index_rangeID || i->value.id() == formula_grammar::indexID)
{
if(i->children.size() == 0)
{
std::string val_s(i->value.begin(), i->value.end());
long value = strtol(val_s.c_str(), NULL, 10);
if(value>=0)
{
ind.push_back(value);
}
else if(value == -1)
{
ind = {(double)(value)};
}
}
else if(i->children.size() == 2)
{
iter_t child = i->children.begin();
string val_s1(child->value.begin(), child->value.end());
long ind_start = strtol(val_s1.c_str(), NULL, 10);
string val_s2((child+1)->value.begin(), (child+1)->value.end());
long ind_end = strtol(val_s2.c_str(), NULL, 10);
if(ind_start>=0 && ind_end>=ind_start)
{
for(int ind_range=ind_start; ind_range<=ind_end; ind_range++)
ind.push_back((double)ind_range);
}
}
}
} }
formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, int ev_ind) //throw (string &), std::out_of_range formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind)
{ {
ostringstream err; ostringstream err;
err << "Evaluating formula: "; err << "";
//iter_t it = i->children.begin(); //iter_t it = i->children.begin();
if (i->value.id() == formula_grammar::val_rID) if (i->value.id() == formula_grammar::val_rID)
...@@ -4241,9 +4585,12 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4241,9 +4585,12 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
} }
string val_d(i->value.begin(), i->value.end()); string val_d(i->value.begin(), i->value.end());
formula_res_t res; formula_res_t res;
res.value = strtod(val_d.c_str(), 0); res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
#ifdef _DEBUG_FORMULA #ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node value real = " << val_d << "(value="<<res.value<<" quality="<<res.quality<<")" << endl; DEBUG_STREAM << " node value real = " << val_d << "(value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<<")" << endl;
#endif #endif
return res; return res;
} }
...@@ -4259,7 +4606,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4259,7 +4606,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value hex = " << val_d << endl; DEBUG_STREAM << " node value hex = " << val_d << endl;
#endif #endif
formula_res_t res; formula_res_t res;
res.value = strtod(val_d.c_str(), 0); res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res; return res;
} }
else if (i->value.id() == formula_grammar::val_stID) else if (i->value.id() == formula_grammar::val_stID)
...@@ -4275,7 +4625,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4275,7 +4625,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl; DEBUG_STREAM << " node value state : " << val_st << "=" << st << endl;
#endif #endif
formula_res_t res; formula_res_t res;
res.value = st; res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res; return res;
} }
else if (i->value.id() == formula_grammar::val_alarm_enum_stID) else if (i->value.id() == formula_grammar::val_alarm_enum_stID)
...@@ -4291,7 +4644,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4291,7 +4644,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value alarm enum state : " << val_st << "=" << st << endl; DEBUG_STREAM << " node value alarm enum state : " << val_st << "=" << st << endl;
#endif #endif
formula_res_t res; formula_res_t res;
res.value = st; res.value = {(double)st};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res; return res;
} }
else if (i->value.id() == formula_grammar::val_qualityID) else if (i->value.id() == formula_grammar::val_qualityID)
...@@ -4308,7 +4664,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4308,7 +4664,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node value quality : " << val_quality << "=" << quality << endl; DEBUG_STREAM << " node value quality : " << val_quality << "=" << quality << endl;
#endif #endif
formula_res_t res; formula_res_t res;
res.value = quality; res.value = {(double)quality};
res.dim_x=1;
res.dim_y=0;
res.valid = true;
return res; return res;
} }
else if (i->value.id() == formula_grammar::unary_exprID) else if (i->value.id() == formula_grammar::unary_exprID)
...@@ -4321,26 +4680,23 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4321,26 +4680,23 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size(); err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();
throw err.str(); throw err.str();
} }
formula_res_t res;
res = eval_expression(i->children.begin(), attr_values);
if (*i->value.begin() == '+') if (*i->value.begin() == '+')
{ {
res.value = + res.value; return eval_expression(i->children.begin(), attr_values);
} }
else if (*i->value.begin() == '-') else if (*i->value.begin() == '-')
{ {
res.value = - res.value; return -eval_expression(i->children.begin(), attr_values);
} }
else if (*i->value.begin() == '!') else if (*i->value.begin() == '!')
{ {
res.value = ! res.value; return !eval_expression(i->children.begin(), attr_values);
} }
else else
{ {
err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed"; err << "in node unary_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str(); throw err.str();
} }
return res;
} }
else if (i->value.id() == formula_grammar::mult_exprID) else if (i->value.id() == formula_grammar::mult_exprID)
{ {
...@@ -4400,49 +4756,104 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4400,49 +4756,104 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node event" << string(i->value.begin(), i->value.end()) << endl; DEBUG_STREAM << " node event" << string(i->value.begin(), i->value.end()) << endl;
#endif #endif
formula_res_t ind; formula_res_t ind;
if(i->children.size() != 2) if(i->children.size() < 2)
{ {
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();; err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();;
throw err.str(); throw err.str();
} }
if((i->children.begin()+1)->value.id() == formula_grammar::indexID) vector<vector<double> > indexes;
ind = eval_expression(i->children.begin()+1, attr_values); //array index iter_t child = i->children.begin();
else if((i->children.begin()+1)->value.id() == formula_grammar::propertyID) if(child->value.id() != formula_grammar::nameID)
{
err << "in node "<< rule_names[i->value.id()]<<"(" << string(i->value.begin(), i->value.end()) << ") expecting " << rule_names[formula_grammar::nameID] << " as first child";
throw err.str();
}
child++;
while(child != i->children.end() && child->value.id() != formula_grammar::propertyID) //eval indexes
{
if(child->value.id() == formula_grammar::index_rangeID || child->value.id() == formula_grammar::indexID)
{
vector<double> ind_range;
eval_index_range(child, attr_values, ind_range);
if(!ind_range.empty())
indexes.push_back(ind_range);
}
else if(child->value.id() == formula_grammar::index_listID)
{
vector<double> ind_list;
iter_t granchild = child->children.begin();
while(granchild != child->children.end() && granchild->value.id() == formula_grammar::index_rangeID) //eval indexes
{
eval_index_range(granchild, attr_values, ind_list);
granchild++;
}
if(!ind_list.empty())
indexes.push_back(ind_list);
}
child++;
}
if(child - i->children.begin() == (long int)i->children.size() -1 && child->value.id() == formula_grammar::propertyID)
{ {
if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".quality") if(string(child->value.begin(), child->value.end()) == ".quality")
{ {
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value); formula_res_t res;
res.value = res.quality; res = eval_expression(i->children.begin(), attr_values);
res.value = {(double)res.quality};
res.dim_x=1;
res.dim_y=0;
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA #ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.quality -> " << res.value << endl; DEBUG_STREAM << " node event.quality -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif #endif
return res; return res;
} }
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".alarm") else if(string(child->value.begin(), child->value.end()) == ".alarm")
{ {
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value); formula_res_t res;
res.value = (res.value == _UNACK) || (res.value == _ACKED); if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _UNACK) || (n == _ACKED)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA #ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.alarm -> " << res.value << endl; DEBUG_STREAM << " node event.alarm -> " << print_array(res.value,res.dim_x,res.dim_y)<< endl;
#endif #endif
return res; return res;
} }
else if(string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()) == ".normal") else if(string(child->value.begin(), child->value.end()) == ".normal")
{ {
formula_res_t res = eval_expression(i->children.begin(), attr_values, (int)ind.value); formula_res_t res;
res.value = (res.value == _NORM) || (res.value == _RTNUN); if(!indexes.empty())
res = eval_expression(i->children.begin(), attr_values, indexes);
else
res = eval_expression(i->children.begin(), attr_values);
std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return (double)((n == _NORM) || (n == _RTNUN)); });
ostringstream temp_attr_val;
temp_attr_val << "\"" << res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA #ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node event.normal -> " << res.value << endl; DEBUG_STREAM << " node event.normal -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
#endif #endif
return res; return res;
} }
} }
else else if(child - i->children.begin() < (long int)i->children.size() -1)//unsupported more indexes/qualities
{ {
err << "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children2 is not an index ->" << string((i->children.begin()+1)->value.begin(), (i->children.begin()+1)->value.end()); err << "expecting indexes or properties after attribute name, found instead: "<< string(child->value.begin(), child->value.end());
throw err.str(); throw err.str();
} }
return eval_expression(i->children.begin(), attr_values, (int)ind.value); if(!indexes.empty())
return eval_expression(i->children.begin(), attr_values, indexes);
else
return eval_expression(i->children.begin(), attr_values);
} }
else if (i->value.id() == formula_grammar::nameID) else if (i->value.id() == formula_grammar::nameID)
{ {
...@@ -4462,37 +4873,412 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4462,37 +4873,412 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if(!it->valid) if(!it->valid)
{ {
if(it->ex_desc.length() > 0) if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'"; err << it->ex_desc << "";
else else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!"; err << "attribute " << string(i->value.begin(), i->value.end()) << " value not valid while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
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();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value not valid, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut(); events->veclock.readerOut();
throw err.str(); //throw err.str();
return res;
} }
else if(it->type != Tango::DEV_STRING && it->value.empty()) else if(it->type != Tango::DEV_STRING && it->value.empty())
{ {
if(it->ex_desc.length() > 0) if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'"; err << it->ex_desc << "";
else else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!"; err << "attribute " << string(i->value.begin(), i->value.end()) << " value not initialized while evaluating formula";
formula_res_t res;
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
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();
res.attr_name = it->name;
ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":{\"Reason\":\"" << res.ex_reason << "\",\"Desc\":\"" << res.ex_desc << "\",\"Origin\":\"" << res.ex_origin << "\"},";
attr_values += temp_attr_val.str();
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " attribute -> " << string(i->value.begin(), i->value.end()) << " value empty, desc=" << res.ex_desc << " quality=" << res.quality << endl;
#endif
events->veclock.readerOut(); events->veclock.readerOut();
throw err.str(); //throw err.str();
} return res;
ostringstream temp_attr_val; }
if(it->value.size() > 1)
temp_attr_val << "\"" << it->name << "[" << ev_ind << "]\":" <<it->value.at(ev_ind) << ",";//throw std::out_of_range
else
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; formula_res_t res;
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality; res.quality = it->quality;
res.ex_reason = it->ex_reason; res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc; res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin; res.ex_origin = it->ex_origin;
res.attr_name = it->name;
ostringstream temp_attr_val;
if(it->value.size() > 0)
{
if(!ev_ind.empty())
{
temp_attr_val << "\"" << it->name;
for(auto vei : ev_ind)
{
if(!vei.empty())
{
temp_attr_val << "[" << print_vector(vei) << "]";
}
}
temp_attr_val << "\":";
if(it->dim_y <=1)//1D array
{
if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1)//single element of 1D array (e.g. [0])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->value.size())
{
err << "Requested element " << ev_ind[0][0] << " is out of bounds with dim=" << it->value.size();
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0])};//throw std::out_of_range
temp_attr_val << "[" << res.value[0] << "],";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() > 1)//multiple elements of 1D array (e.g. [0,1,2])
{
res.dim_y = 0;
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
res.value.push_back(it->value.at(ei0));//throw std::out_of_range
}
}
res.dim_x = res.value.size();
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) << ",";
}
else if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0]==-1)//all elements of 1D array (e.g. [-1])
{
res.dim_y = 0;
res.value = it->value;
res.dim_x = it->dim_x;
temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) <<",";
}
else
{
err << "UNSUPPORTED additional indexes in 1D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else if(it->dim_y > 1)//2D array
{
//single row of 2D array (e.g. [0] or [0][-1])
if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] != -1) // and first index not -1
{
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ev_ind[0][0] * (it->dim_x)));
advance(vend,(int)(ev_ind[0][0]+1) * it->dim_x);
res.value = value_t(vstart,vend);
temp_attr_val << "" << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() > 1)//multiple rows of 2D array (e.g. [0,1,2] or [0,1,2][-1])
{
res.dim_x = it->dim_x;
res.dim_y = ev_ind[0].size();
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->value.size())
{
err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
else
{
auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
advance(vstart,(int)(ei0 * (it->dim_x)));
advance(vend,(int)(ei0+1) * it->dim_x);
value_t row = value_t(vstart,vend);
res.value.insert(
res.value.end(),
std::make_move_iterator(row.begin()),
std::make_move_iterator(row.end())
);
}
}
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if((ev_ind.size() == 1 || //only first index
(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
&& ev_ind[0].size() == 1 && ev_ind[0][0] == -1)//all rows of 2D array (e.g. [-1] or [-1][-1])
{
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.value = it->value;
temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single element of 2D array (e.g. [0][1])
{
res.dim_x = 1;
res.dim_y = 0;
if(ev_ind[0][0] >= it->dim_y)
{
err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
if(ev_ind[1][0] >= it->dim_x)
{
err << "Requested column " << ev_ind[1][0] << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value = {it->value.at(ev_ind[0][0]*it->dim_x + ev_ind[1][0])};//throw std::out_of_range
temp_attr_val << "[" <<res.value[0] << "],";//throw std::out_of_range
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column slice of 2D array (e.g. [0,1,2][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column of 2D array (e.g. [-1][3])
{
res.dim_x = 1;
long ei1 = ev_ind[1][0];
if(ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() > 1)//single row slice of 2D array (e.g. [0][1,2,3])
{
res.dim_y = 0;
long ei0 = ev_ind[0][0];
if(ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
res.dim_x = ev_ind[1].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [0,1][2,3])
{
for(auto ei0 : ev_ind[0])
{
if(ei0 < 0 || ei0 >= it->dim_y)
{
err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = ev_ind[0].size();
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [-1][2,3])
{
for(long ei0 = 0; ei0 < it->dim_y; ei0++)
{
for(auto ei1 : ev_ind[1])
{
if(ei1 < 0 || ei1 >= it->dim_x)
{
err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
temp_attr_val << "[]";
events->veclock.readerOut();
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"OUT_OF_RANGE",
err.str(),
it->name);
}
res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw std::out_of_range
}
}
res.dim_x = ev_ind[1].size();
res.dim_y = it->dim_y;
temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
}
else //ev_ind.size() > 2
{
err << "UNSUPPORTED additional indexes in 2D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else //TODO N-DIMENSIONAL arrays
{
err << "UNSUPPORTED array indexes: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
DEBUG_STREAM << __func__ << ": " << err.str() << endl;
events->veclock.readerOut();
throw err.str();
}
}
else
{
res.value = it->value;
temp_attr_val << "\"" << it->name << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
}
}
else
temp_attr_val << "\"" << it->name << "\":[],";
attr_values += temp_attr_val.str();
events->veclock.readerOut();
#ifdef _DEBUG_FORMULA #ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl; DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif #endif
res.value = it->value.at(ev_ind); //throw std::out_of_range
events->veclock.readerOut();
return res; return res;
} }
else else
...@@ -4514,7 +5300,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4514,7 +5300,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
DEBUG_STREAM << " node index = " << val_d << endl; DEBUG_STREAM << " node index = " << val_d << endl;
#endif #endif
formula_res_t res; formula_res_t res;
res.value = strtod(val_d.c_str(), 0); res.valid = true;
res.value = {(strtod(val_d.c_str(), 0))};
res.dim_x=1;
res.dim_y=0;
return res; return res;
} }
else if (i->value.id() == formula_grammar::logical_exprID) else if (i->value.id() == formula_grammar::logical_exprID)
...@@ -4555,43 +5344,72 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4555,43 +5344,72 @@ 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), formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values); res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2; vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!"); string err2("Non int value in bitwise operation");
val_l1 = (long)trunc(res_1.value); //transform to long std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
val_l2 = (long)trunc(res_2.value); //transform to long [](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf [](double n) { return (long)trunc(n); });//transform to long
throw err2; size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception( //throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (*i->value.begin() == '&') if (*i->value.begin() == '&')
{ {
formula_res_t res; formula_res_t res;
res.value = (double)(val_l1 & val_l2); res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.quality = res.combine_quality(res_1.quality, res_2.quality); res.valid = valid;
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); if(!res.valid)
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); 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);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y,val_l2,res_2.dim_x,res_2.dim_y,res.value,res.dim_x,res.dim_y, "Bitwise &", vectorUtils::fBitAnd);
return res; return res;
} }
else if (*i->value.begin() == '|') else if (*i->value.begin() == '|')
{ {
formula_res_t res; formula_res_t res;
res.value = (double)(val_l1 | val_l2); res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.quality = res.combine_quality(res_1.quality, res_2.quality); res.valid = valid;
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); if(!res.valid)
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); 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);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise |", vectorUtils::fBitOr);
return res; return res;
} }
else if (*i->value.begin() == '^') else if (*i->value.begin() == '^')
{ {
formula_res_t res; formula_res_t res;
res.value = (double)(val_l1 ^ val_l2); res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.quality = res.combine_quality(res_1.quality, res_2.quality); res.valid = valid;
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); if(!res.valid)
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); 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);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise ^", vectorUtils::fBitXor);
return res; return res;
} }
else else
...@@ -4612,33 +5430,59 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4612,33 +5430,59 @@ 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), formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, attr_values); res_2=eval_expression(i->children.begin()+1, attr_values);
long val_l1,val_l2; vector<long> val_l1(res_1.value.size()),val_l2(res_2.value.size());
bool valid = res_1.valid && res_2.valid;
string err2("ERROR: non-int value in bitwise operation!"); string err2("Non int value in bitwise operation");
val_l1 = (long)trunc(res_1.value); //transform to long std::transform(res_1.value.begin(), res_1.value.end(), val_l1.begin(),
val_l2 = (long)trunc(res_2.value); //transform to long [](double n) { return (long)trunc(n); });//transform to long
std::transform(res_2.value.begin(), res_2.value.end(), val_l2.begin(),
if((val_l1 != res_1.value) || (val_l2 != res_2.value)) //if different, lost something with truncf [](double n) { return (long)trunc(n); });//transform to long
throw err2; bool non_int_error=false;
size_t ii;
for(ii=0; ii<res_1.value.size(); ii++)
{
if(val_l1[ii] != res_1.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
for(ii=0; ii<res_2.value.size(); ii++)
{
if(val_l2[ii] != res_2.value[ii]) //if different, lost something with truncf
Tango::Except::throw_exception(//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
(const char *)"FORMULA_ERROR",
err2,
string("Bitwise ") + string(i->value.begin(), i->value.end()));
}
if (string(i->value.begin(), i->value.end()) == string("<<")) if (string(i->value.begin(), i->value.end()) == string("<<"))
{ {
formula_res_t res; formula_res_t res;
res.value = (double)(val_l1 << val_l2); res.quality = res.combine_quality(res_1.quality, res_2.quality);
res.quality = res.combine_quality(res_1.quality, res_2.quality); res.valid = valid;
res.ex_reason = res.combine_exception(res_1.ex_reason, res_2.ex_reason); if(!res.valid)
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); 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);
}
vectorUtils::applyVectorFunc(val_l1, res_2.dim_x,res_2.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise <<", vectorUtils::fBitShiftL);
return res; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string(">>")) else if (string(i->value.begin(), i->value.end()) == string(">>"))
{ {
formula_res_t res; formula_res_t res;
res.value = (double)(val_l1 >> val_l2);
res.quality = res.combine_quality(res_1.quality, res_2.quality); 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.valid = valid;
res.ex_desc = res.combine_exception(res_1.ex_desc, res_2.ex_desc); if(!res.valid)
res.ex_origin = res.combine_exception(res_1.ex_origin, res_2.ex_origin); {
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);
}
vectorUtils::applyVectorFunc(val_l1, res_1.dim_x,res_1.dim_y, val_l2,res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, "Bitwise >>", vectorUtils::fBitShiftR);
return res; return res;
} }
else else
...@@ -4684,20 +5528,45 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4684,20 +5528,45 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
err << "in node equality_exprID -> nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!"; err << "in node equality_exprID -> nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not valid!";
if(it->ex_desc.length() > 0) if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'"; err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut(); events->veclock.readerOut();
throw err.str(); /*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
} }
else if(it->type != Tango::DEV_STRING && it->value.empty()) else if(it->type != Tango::DEV_STRING && it->value.empty())
{ {
err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!"; err << "in node nameID(" << string(i2_1->value.begin(), i2_1->value.end()) << ") value not initialized!!";
if(it->ex_desc.length() > 0) if(it->ex_desc.length() > 0)
err << " EX: '" << it->ex_desc << "'"; err << " EX: '" << it->ex_desc << "'";
res.valid = false;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
events->veclock.readerOut(); events->veclock.readerOut();
throw err.str(); /*Tango::Except::throw_exception( //throw exception to have error not delayed
it->ex_reason,//or Event_ERROR
it->ex_desc,
it->ex_origin);*/
return res;
} }
ostringstream temp_attr_val; ostringstream temp_attr_val;
temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\","; temp_attr_val << "\"" << it->name << "\":\"" <<it->value_string << "\",";
attr_values += temp_attr_val.str(); attr_values += temp_attr_val.str();
res.valid = true;
res.dim_x = it->dim_x;
res.dim_y = it->dim_y;
res.quality = it->quality; res.quality = it->quality;
res.ex_reason = it->ex_reason; res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc; res.ex_desc = it->ex_desc;
...@@ -4720,12 +5589,16 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4720,12 +5589,16 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("!=")) if (string(i->value.begin(), i->value.end()) == string("!="))
{ {
res.value = attr_val != val_string; res.value = {(double)(attr_val != val_string)};
res.dim_x=1;
res.dim_y=0;
return res; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("==")) else if (string(i->value.begin(), i->value.end()) == string("=="))
{ {
res.value = attr_val == val_string; res.value = {(double)(attr_val == val_string)};
res.dim_x=1;
res.dim_y=0;
return res; return res;
} }
else else
...@@ -4786,7 +5659,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4786,7 +5659,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
} }
else else
{ {
err << "in node equality_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed"; err << "in node compare_exprID(" << string(i->value.begin(), i->value.end()) << ") value not allowed";
throw err.str(); throw err.str();
} }
} }
...@@ -4805,109 +5678,49 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4805,109 +5678,49 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
if (string(i->value.begin(), i->value.end()) == string("abs")) if (string(i->value.begin(), i->value.end()) == string("abs"))
{ {
res = eval_expression(i->children.begin(), attr_values); res = eval_expression(i->children.begin(), attr_values);
res.value = fabs(res.value); std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return fabs(n); });
return res; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("cos")) else if (string(i->value.begin(), i->value.end()) == string("cos"))
{ {
res = eval_expression(i->children.begin(), attr_values); res = eval_expression(i->children.begin(), attr_values);
res.value = cos(res.value); std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return cos(n); });
return res; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("sin")) else if (string(i->value.begin(), i->value.end()) == string("sin"))
{ {
res = eval_expression(i->children.begin(), attr_values); res = eval_expression(i->children.begin(), attr_values);
res.value = sin(res.value); std::transform(res.value.begin(), res.value.end(), res.value.begin(),
[](double n) { return sin(n); });
return res; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("quality")) else if (string(i->value.begin(), i->value.end()) == string("quality"))
{ {
res = eval_expression(i->children.begin(), attr_values); res = eval_expression(i->children.begin(), attr_values);
res.value = res.quality; res.value = {(double)res.quality};//ignore values and keep quality as result
res.dim_x=1;
res.dim_y=0;
return res; return res;
} }
else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")) && i->children.begin()->value.id() == formula_grammar::nameID) else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")))
{ {
events->veclock.readerIn(); res = eval_expression(i->children.begin(), attr_values);
vector<event>::iterator it = events->v_event.begin(); res.dim_x=1;
string s(i->children.begin()->value.begin(), i->children.begin()->value.end()); res.dim_y=0;
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase if(string(i->value.begin(), i->value.end()) == string("AND"))
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " -> " << string(i->value.begin(), i->value.end()) << "(" << s << ")" << endl;
#endif
while ((it != events->v_event.end()) && (it->name != s))
it++;
if (it != events->v_event.end())
{ {
if(!it->valid) res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)true, [](bool acc, double n) { return (bool)(acc && (bool)(n));})};
{
err << "in node funcID(" << string(i->value.begin(), i->value.end()) << "), (" << s << ") value not valid!" << ends;
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not valid!";
events->veclock.readerOut();
throw err.str();
}
else if(it->type != Tango::DEV_STRING && it->value.empty())
{
if(it->ex_desc.length() > 0)
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' exception: '" << it->ex_desc << "'";
else
err << "attribute '" << string(i->value.begin(), i->value.end()) << "' value not initialized!!";
events->veclock.readerOut();
throw err.str();
}
ostringstream temp_attr_val;
bool result;
if (string(i->value.begin(), i->value.end()) == string("AND"))
result = true;
else if (string(i->value.begin(), i->value.end()) == string("OR"))
result = false;
temp_attr_val << "\"" << it->name << "\":";
if(it->read_size > 1)
temp_attr_val << "[";
for(int att_ind = 0; att_ind < it->read_size && att_ind < it->value.size(); att_ind++)
{
temp_attr_val << it->value.at(att_ind);
if (string(i->value.begin(), i->value.end()) == string("AND"))
{
result = result && (bool)it->value.at(att_ind);
if(!result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
else if (string(i->value.begin(), i->value.end()) == string("OR"))
{
result = result || (bool)it->value.at(att_ind);
if(result) //comment to have all array values in attr_values
break; //comment to have all array values in attr_values
}
if(att_ind < it->read_size-1 && att_ind < it->value.size()-1)
temp_attr_val << ",";
}
if(it->read_size > 1)
temp_attr_val << "]";
temp_attr_val << ",";
attr_values += temp_attr_val.str();
res.quality = it->quality;
res.ex_reason = it->ex_reason;
res.ex_desc = it->ex_desc;
res.ex_origin = it->ex_origin;
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node name -> " << temp_attr_val.str() << " quality=" << res.quality << endl;
#endif
res.value = result;
events->veclock.readerOut();
return res;
} }
else else if(string(i->value.begin(), i->value.end()) == string("OR"))
{ {
events->veclock.readerOut(); res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)false, [](bool acc, double n) { return (bool)(acc || (bool)(n));})};
err << "in function " << string(i->value.begin(), i->value.end()) << " event (" << s << ") not found in event table" << ends;
throw err.str();
} }
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node funcID("<<string(i->value.begin(), i->value.end())<<") value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<< endl;
#endif
return res;
} }
else else
{ {
...@@ -4927,34 +5740,47 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4927,34 +5740,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), formula_res_t res_1=eval_expression(i->children.begin(), attr_values),
res_2=eval_expression(i->children.begin()+1, 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")) if (string(i->value.begin(), i->value.end()) == string("min"))
{ {
formula_res_t res; formula_res_t res;
res.value = min(res_1.value, res_2.value); vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMin);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality); 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); if(!res.valid)
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); 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; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("max")) else if (string(i->value.begin(), i->value.end()) == string("max"))
{ {
formula_res_t res; formula_res_t res;
res.value = max(res_1.value, res_2.value); vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fMax);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality); 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); if(!res.valid)
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); 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; return res;
} }
else if (string(i->value.begin(), i->value.end()) == string("pow")) else if (string(i->value.begin(), i->value.end()) == string("pow"))
{ {
formula_res_t res; formula_res_t res;
res.value = pow(res_1.value, res_2.value); vectorUtils::applyVectorFunc(res_1.value, res_1.dim_x,res_1.dim_y, res_2.value, res_2.dim_x,res_2.dim_y, res.value,res.dim_x,res.dim_y, string(i->value.begin(), i->value.end()), vectorUtils::fPow);
res.valid = valid;
res.quality = res.combine_quality(res_1.quality, res_2.quality); 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); if(!res.valid)
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); 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; return res;
} }
else else
...@@ -4974,7 +5800,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4974,7 +5800,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
throw err.str(); throw err.str();
} }
formula_res_t res_1=eval_expression(i->children.begin(), attr_values); formula_res_t res_1=eval_expression(i->children.begin(), attr_values);
if(res_1.value) if(!res_1.valid || res_1.value.empty())
{
#ifdef _DEBUG_FORMULA
DEBUG_STREAM << " node ternary_if expression: returning Error=" << res_1.ex_desc << endl;
#endif
return res_1;
}
res_1.extract_result();
if(res_1.value[0])
{ {
formula_res_t res = eval_expression(i->children.begin()+1, attr_values); formula_res_t res = eval_expression(i->children.begin()+1, attr_values);
return res; return res;
...@@ -4996,7 +5830,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values ...@@ -4996,7 +5830,10 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
} }
} }
formula_res_t res; formula_res_t res;
res.value = 0; res.value = {(double)0.0};
res.dim_x=1;
res.dim_y=0;
res.valid = false;
return res; return res;
} }
...@@ -5029,7 +5866,7 @@ void AlarmHandler::eval_node_event(iter_t const& i, vector<string> & ev) ...@@ -5029,7 +5866,7 @@ void AlarmHandler::eval_node_event(iter_t const& i, vector<string> & ev)
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))tolower); //transform to lowercase
ev.push_back(s); ev.push_back(s);
} }
//cout << endl; //TANGO_LOG << endl;
//iter_t it = i->children.begin(); //iter_t it = i->children.begin();
for(iter_t it = i->children.begin(); it != i->children.end(); it++) for(iter_t it = i->children.begin(); it != i->children.end(); it++)
eval_node_event(it, ev); eval_node_event(it, ev);
...@@ -5053,6 +5890,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5053,6 +5890,7 @@ void AlarmHandler::prepare_alarm_attr()
silencedAlarms_sz=0; silencedAlarms_sz=0;
listAlarms_sz=0; listAlarms_sz=0;
alarmSummary_sz=0; alarmSummary_sz=0;
alarmDisabled_sz=0;
string almstate; string almstate;
for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) { for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
...@@ -5064,6 +5902,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5064,6 +5902,7 @@ void AlarmHandler::prepare_alarm_attr()
string alm_summary; string alm_summary;
alm_summary += KEY(NAME_KEY) + ai->first + SEP; alm_summary += KEY(NAME_KEY) + ai->first + SEP;
#endif #endif
stringstream alm_disabled;
if(ai->second.enabled == false) if(ai->second.enabled == false)
{ {
outOfServiceAlarms_read[outOfServiceAlarms_sz] = ai->second.name; outOfServiceAlarms_read[outOfServiceAlarms_sz] = ai->second.name;
...@@ -5086,7 +5925,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5086,7 +5925,7 @@ void AlarmHandler::prepare_alarm_attr()
} }
else 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; acknowledgedAlarms_read[acknowledgedAlarms_sz] = ai->second.name;
attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str()); attr_alarmAcknowledged_read[acknowledgedAlarms_sz] = const_cast<char*>(acknowledgedAlarms_read[acknowledgedAlarms_sz].c_str());
...@@ -5096,7 +5935,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5096,7 +5935,7 @@ void AlarmHandler::prepare_alarm_attr()
acknowledgedAlarms_sz++; acknowledgedAlarms_sz++;
almstate = "ACKED"; 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; unacknowledgedAlarms_read[unacknowledgedAlarms_sz] = ai->second.name;
attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str()); attr_alarmUnacknowledged_read[unacknowledgedAlarms_sz] = const_cast<char*>(unacknowledgedAlarms_read[unacknowledgedAlarms_sz].c_str());
...@@ -5106,7 +5945,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5106,7 +5945,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedAlarms_sz++; unacknowledgedAlarms_sz++;
almstate = "UNACK"; 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; unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz] = ai->second.name;
attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str()); attr_alarmUnacknowledgedNormal_read[unacknowledgedNormalAlarms_sz] = const_cast<char*>(unacknowledgedNormalAlarms_read[unacknowledgedNormalAlarms_sz].c_str());
...@@ -5116,7 +5955,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5116,7 +5955,7 @@ void AlarmHandler::prepare_alarm_attr()
unacknowledgedNormalAlarms_sz++; unacknowledgedNormalAlarms_sz++;
almstate = "RTNUN"; 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; normalAlarms_read[normalAlarms_sz] = ai->second.name;
attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str()); attr_alarmNormal_read[normalAlarms_sz] = const_cast<char*>(normalAlarms_read[normalAlarms_sz].c_str());
...@@ -5137,6 +5976,38 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5137,6 +5976,38 @@ void AlarmHandler::prepare_alarm_attr()
} }
} }
tm time_tm;
time_t time_sec= ai->second.ts_time_silenced.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
if(almstate == "OOSRV" || almstate == "SHLVD")
{
//TANGO_LOG << __func__ << ": " << ai->first << " silenced="<< ai->second.silenced << endl;
#if 0
alm_disabled << KEY(ALARM_TIME_KEY) << time_buf << "." << ai->second.ts.tv_usec << SEP;
alm_disabled << KEY(NAME_KEY) << ai->first << SEP;
alm_disabled << KEY(VALUE_KEY) << almstate << SEP; //TODO: string or enum value?
alm_disabled << KEY(SILENT_TIME_REMAINING_KEY) << ai->second.silenced << SEP;
alm_disabled << KEY(MESSAGE_KEY) << ai->second.msg; //TODO: escape ';'
#else
alm_disabled << ai->second.ts.tv_sec << "\t";
alm_disabled << ai->second.ts.tv_usec << "\t";
alm_disabled << ai->first << "\t";
alm_disabled << almstate << "\t"; //TODO: string or enum value?
alm_disabled << ai->second.ack << "\t";
alm_disabled << ai->second.lev << "\t";
alm_disabled << ai->second.silenced << "\t";
alm_disabled << ai->second.grp2str() << "\t";
alm_disabled << ai->second.msg << "\t"; //TODO: escape ';'
#endif
alarmDisabled_read[alarmDisabled_sz] = alm_disabled.str();
attr_alarmDisabled_read[alarmDisabled_sz] = const_cast<char*>(alarmDisabled_read[alarmDisabled_sz].c_str());
alarmDisabled_sz++;
}
ostringstream tmp_ex; ostringstream tmp_ex;
//tmp_ex.str(""); //tmp_ex.str("");
if(ai->second.error) if(ai->second.error)
...@@ -5149,11 +6020,9 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5149,11 +6020,9 @@ void AlarmHandler::prepare_alarm_attr()
} }
} }
tm time_tm; time_sec= ai->second.ts.tv_sec;
time_t time_sec= ai->second.ts.tv_sec;
//gmtime_r(&time_sec,&time_tm); //-> UTC //gmtime_r(&time_sec,&time_tm); //-> UTC
localtime_r(&time_sec,&time_tm); localtime_r(&time_sec,&time_tm);
char time_buf[64];
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm); strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
#ifndef ALM_SUM_STR #ifndef ALM_SUM_STR
...@@ -5251,17 +6120,18 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5251,17 +6120,18 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from * found, change stat only if switching from
* S_NORMAL or S_ALARM status to S_ERROR * S_NORMAL or S_ALARM status to S_ERROR
*/ */
//cout << "read_attr(): S_ERROR: found: " << aid->name << endl; //TANGO_LOG << "read_attr(): S_ERROR: found: " << aid->name << endl;
if (aid->stat != S_ERROR) { if (aid->stat != S_ERROR) {
aid->stat = S_ERROR; aid->stat = S_ERROR;
aid->ack = NOT_ACK; aid->ack = NOT_ACK;
aid->ts = ai->second.ts; aid->ts = ai->second.ts;
aid->msg = it->second.ex_desc;//tmp_ex.str();//ai->second.msg; aid->msg = ai->second.ex_desc;//tmp_ex.str();//ai->second.msg;
aid->url = ai->second.url; aid->url = ai->second.url;
} }
aid->grp = ai->second.grp; aid->grp = ai->second.grp;
aid->lev = ai->second.lev; aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0 //ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC #ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter); aid->on_counter.store(ai->second.on_counter);
...@@ -5276,7 +6146,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5276,7 +6146,7 @@ void AlarmHandler::prepare_alarm_attr()
} else { } else {
alarm_t at = ai->second; alarm_t at = ai->second;
at.stat = S_ERROR; at.stat = S_ERROR;
at.msg = it->second.ex_desc;//tmp_ex.str();//ai->second.msg; at.msg = ai->second.ex_desc;//tmp_ex.str();//ai->second.msg;
/* /*
* not found: new "alarmed" item * not found: new "alarmed" item
*/ */
...@@ -5301,7 +6171,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5301,7 +6171,7 @@ void AlarmHandler::prepare_alarm_attr()
* found, change stat only if switching from * found, change stat only if switching from
* S_NORMAL to S_ALARM status * S_NORMAL to S_ALARM status
*/ */
//cout << "read_attr(): S_ALARM: found: " << aid->name << endl; //TANGO_LOG << "read_attr(): S_ALARM: found: " << aid->name << endl;
if (aid->stat == S_NORMAL || aid->stat == S_ERROR) { if (aid->stat == S_NORMAL || aid->stat == S_ERROR) {
aid->stat = S_ALARM; aid->stat = S_ALARM;
aid->ack = NOT_ACK; aid->ack = NOT_ACK;
...@@ -5312,6 +6182,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5312,6 +6182,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->grp = ai->second.grp; aid->grp = ai->second.grp;
aid->lev = ai->second.lev; aid->lev = ai->second.lev;
aid->is_new = ai->second.is_new; //copy is_new state aid->is_new = ai->second.is_new; //copy is_new state
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0 //ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
#ifdef _CNT_ATOMIC #ifdef _CNT_ATOMIC
aid->on_counter.store(ai->second.on_counter); aid->on_counter.store(ai->second.on_counter);
...@@ -5366,6 +6237,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5366,6 +6237,7 @@ void AlarmHandler::prepare_alarm_attr()
aid->is_new = ai->second.is_new; //copy is_new state aid->is_new = ai->second.is_new; //copy is_new state
aid->silenced = ai->second.silenced; //update silenced from alarm table (maybe not necessary) aid->silenced = ai->second.silenced; //update silenced from alarm table (maybe not necessary)
aid->silent_time = ai->second.silent_time; //if already alarmed and not saved correctly in properties needed to update aid->silent_time = ai->second.silent_time; //if already alarmed and not saved correctly in properties needed to update
aid->receivers = ai->second.receivers;
//ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0 //ai->second.is_new = 0; //and set state as not more new //12-06-08: StopNew command set it to 0
if (aid->ack == ACK) { if (aid->ack == ACK) {
//if (aid->done) //TODO: done seems useless //if (aid->done) //TODO: done seems useless
...@@ -5438,7 +6310,7 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5438,7 +6310,7 @@ void AlarmHandler::prepare_alarm_attr()
is_new = (aid->is_new && aid->silenced <= 0) ? "NEW" : " "; is_new = (aid->is_new && aid->silenced <= 0) ? "NEW" : " ";
os << aid->ts.tv_sec << "\t" << aid->ts.tv_usec << "\t" \ os << aid->ts.tv_sec << "\t" << aid->ts.tv_usec << "\t" \
<< aid->name << "\t" << aid->stat << "\t" << aid->ack \ << aid->name << "\t" << aid->stat << "\t" << aid->ack \
<< "\t" << aid->on_counter << "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new; << "\t" << aid->lev << "\t" << aid->silenced << "\t" << aid->grp2str() << "\t" << aid->msg << "\t" << is_new;
tmp_alarm_table.push_back(os.str()); tmp_alarm_table.push_back(os.str());
} }
} }
...@@ -5465,18 +6337,20 @@ void AlarmHandler::prepare_alarm_attr() ...@@ -5465,18 +6337,20 @@ void AlarmHandler::prepare_alarm_attr()
strncpy(dss[i],tmp_alarm_table[i].c_str(), len); strncpy(dss[i],tmp_alarm_table[i].c_str(), len);
dss[i][len]=0; dss[i][len]=0;
} }
#ifdef _ZEROS_ALARM_EMPTY
if(ds_num == 0) if(ds_num == 0)
{ {
ostringstream os1; ostringstream os1;
ds_num++; ds_num++;
os1.clear(); os1.clear();
os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t "; os1 << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << 0 << "\t" << -1 << "\t" << 0 << "\t" << 0 << "\t ";
//ds[0] = CORBA::string_dup(os1.str().c_str()); //ds[0] = CORBA::string_dup(os1.str().c_str());
size_t len=os1.str().length(); size_t len=os1.str().length();
if(len >= 10124) len = 10124-1; if(len >= 10124) len = 10124-1;
strncpy(dss[i],os1.str().c_str(), len); strncpy(dss[i],os1.str().c_str(), len);
dss[i][len]=0; dss[i][len]=0;
} }
#endif
dslock->writerOut(); dslock->writerOut();
} }
...@@ -5566,7 +6440,7 @@ void AlarmHandler::put_signal_property() ...@@ -5566,7 +6440,7 @@ void AlarmHandler::put_signal_property()
DECLARE_TIME_VAR t0, t1; DECLARE_TIME_VAR t0, t1;
GET_TIME(t0); GET_TIME(t0);
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled, alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time); it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1); GET_TIME(t1);
DEBUG_STREAM << __func__ << ": SAVED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl; DEBUG_STREAM << __func__ << ": SAVED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//alarms.vlock->readerOut();//TODO: avoid keeping lock //alarms.vlock->readerOut();//TODO: avoid keeping lock
...@@ -5589,7 +6463,7 @@ void AlarmHandler::put_signal_property() ...@@ -5589,7 +6463,7 @@ void AlarmHandler::put_signal_property()
itmap->second = conf_string; itmap->second = conf_string;
savedlock->readerOut(); savedlock->readerOut();
alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled, alarms.save_alarm_conf_db(it.second.attr_name,it.second.name,it.second.stat,it.second.ack,it.second.enabled,
it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.silent_time); it.second.formula,it.second.on_delay,it.second.off_delay,it.second.grp2str(),it.second.lev,it.second.msg,it.second.url,it.second.cmd_name_a,it.second.cmd_name_n,it.second.receivers,it.second.silent_time);
GET_TIME(t1); GET_TIME(t1);
DEBUG_STREAM << __func__ << ": UPDATED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl; DEBUG_STREAM << __func__ << ": UPDATED '" <<it.first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
} }
...@@ -5600,8 +6474,13 @@ void AlarmHandler::put_signal_property() ...@@ -5600,8 +6474,13 @@ void AlarmHandler::put_signal_property()
} }
} }
// Identify the alarms that need to be removed.
// The alarms that have been identified to be removed have their tag
// stored in a std::vector. The vector is later iterated over in a second
// step when the alarms get removed.
savedlock->readerIn(); savedlock->readerIn();
map<string, string>::iterator it2=saved_alarms.begin(); map<string, string>::iterator it2=saved_alarms.begin();
vector< string > alarms_to_be_erased;
while(it2 != saved_alarms.end()) while(it2 != saved_alarms.end())
{ {
if(!it2->first.empty())//TODO: should not be needed, bug if it happens if(!it2->first.empty())//TODO: should not be needed, bug if it happens
...@@ -5609,25 +6488,30 @@ void AlarmHandler::put_signal_property() ...@@ -5609,25 +6488,30 @@ void AlarmHandler::put_signal_property()
auto found = local_alarms.find(it2->first); auto found = local_alarms.find(it2->first);
if (found == local_alarms.end()) if (found == local_alarms.end())
{ {
DEBUG_STREAM << __func__<<": DELETING '" << it2->first << "'" << endl; alarms_to_be_erased.push_back(it2->first);
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(it2->first);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" <<it2->first << "' in " << ELAPSED(t0, t1) << " ms" << endl;
//savedlock->readerOut();//TODO: with boost shared lock to be released to take exclusive
savedlock->writerIn();
saved_alarms.erase(it2);
savedlock->writerOut();
//savedlock->readerIn();
} }
} }
if(it2 != saved_alarms.end()) if(it2 != saved_alarms.end())
it2++; it2++;
} }
savedlock->readerOut(); savedlock->readerOut();
// Now remove the alarms from the property in the TangoDB and saved_alarms.
if(!alarms_to_be_erased.empty())
{
savedlock->writerIn();
for(auto iter{alarms_to_be_erased.begin()}; iter != alarms_to_be_erased.end(); ++iter)
{
DEBUG_STREAM << __func__<<": DELETING '" << *iter << "' saved_alarms.size=" << saved_alarms.size() << endl;
DECLARE_TIME_VAR t0, t1;
GET_TIME(t0);
alarms.delete_alarm_conf_db(*iter);
GET_TIME(t1);
DEBUG_STREAM << __func__ << ": DELETED '" << *iter << "' in " << ELAPSED(t0, t1) << " ms saved_alarms.size=" << saved_alarms.size() << endl;
saved_alarms.erase(saved_alarms.find(*iter));
}
savedlock->writerOut();
}
Tango::DbData data; Tango::DbData data;
data.push_back(Tango::DbDatum("AlarmList")); data.push_back(Tango::DbDatum("AlarmList"));
...@@ -5738,6 +6622,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm) ...@@ -5738,6 +6622,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
alm.dp_n = NULL; alm.dp_n = NULL;
alm.enabled=true; alm.enabled=true;
alm.shelved=false; alm.shelved=false;
alm.receivers.clear();
alm.formula_tree = alm.formula_tree =
//boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp = //boost::spirit::tree_parse_info< std::string::iterator, factory_t> tmp =
...@@ -5761,6 +6646,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm) ...@@ -5761,6 +6646,7 @@ void AlarmHandler::parse_alarm(string &alarm_string, alarm_t &alm)
std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase std::transform(alm.lev.begin(), alm.lev.end(), alm.lev.begin(), (int(*)(int))tolower); //transform to lowercase
alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";" alm.msg = std::regex_replace(alm.msg, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";" alm.url = std::regex_replace(alm.url, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
alm.receivers = std::regex_replace(alm.receivers, std::regex(R"((\\;)|(;;))"), ";"); //match raw string "\;" or ";;" and replace with ";"
if(alm.cmd_name_a.length() > 0) if(alm.cmd_name_a.length() > 0)
{ {
const char *c = alm.cmd_name_a.c_str(); const char *c = alm.cmd_name_a.c_str();
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#ifndef AlarmHandler_H #ifndef AlarmHandler_H
#define AlarmHandler_H #define AlarmHandler_H
#include <tango.h> #include <tango/tango.h>
#include <boost/version.hpp> #include <boost/version.hpp>
#if BOOST_VERSION >= 103600 #if BOOST_VERSION >= 103600
...@@ -61,7 +61,15 @@ class update_thread; ...@@ -61,7 +61,15 @@ class update_thread;
# define ELAPSED(before, after) \ # define ELAPSED(before, after) \
1000.0*(after.tv_sec-before.tv_sec) + \ 1000.0*(after.tv_sec-before.tv_sec) + \
((double)after.tv_usec-before.tv_usec) / 1000 ((double)after.tv_usec-before.tv_usec) / 1000
#ifndef TANGO_LOG
#define TANGO_LOG cout
#endif
#ifndef TANGO_LOG_INFO
#define TANGO_LOG_INFO cout2
#endif
#ifndef TANGO_LOG_DEBUG
#define TANGO_LOG_DEBUG cout4
#endif
/*----- PROTECTED REGION END -----*/ // AlarmHandler.h /*----- PROTECTED REGION END -----*/ // AlarmHandler.h
...@@ -100,10 +108,6 @@ class AlarmHandler : public TANGO_BASE_CLASS ...@@ -100,10 +108,6 @@ class AlarmHandler : public TANGO_BASE_CLASS
public: public:
bool compare_without_domain(string str1, string str2); bool compare_without_domain(string str1, string str2);
string remove_domain(string str); string remove_domain(string str);
//TODO: real attributes
Tango::DevLong attr_AttributeStartedNumber_read;
Tango::DevLong attr_AttributePausedNumber_read;
Tango::DevLong attr_AttributeStoppedNumber_read;
Tango::DevLong attr_AttributeNumber_read; Tango::DevLong attr_AttributeNumber_read;
string normalAlarms_read[MAX_ALARMS]; string normalAlarms_read[MAX_ALARMS];
...@@ -117,6 +121,7 @@ public: ...@@ -117,6 +121,7 @@ public:
string alarmSummary_read[MAX_ALARMS]; string alarmSummary_read[MAX_ALARMS];
string eventList_read[MAX_ATTR_SUMMARY]; string eventList_read[MAX_ATTR_SUMMARY];
string eventSummary_read[MAX_ATTR_SUMMARY]; string eventSummary_read[MAX_ATTR_SUMMARY];
string alarmDisabled_read[MAX_ALARMS];
/* char c_normalAlarms_read[MAX_ALARMS][MAX_ATTR_NAME]; /* char c_normalAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
char c_unacknowledgedAlarms_read[MAX_ALARMS][MAX_ATTR_NAME]; char c_unacknowledgedAlarms_read[MAX_ALARMS][MAX_ATTR_NAME];
...@@ -140,6 +145,7 @@ public: ...@@ -140,6 +145,7 @@ public:
size_t alarmSummary_sz; size_t alarmSummary_sz;
size_t eventList_sz; size_t eventList_sz;
size_t eventSummary_sz; size_t eventSummary_sz;
size_t alarmDisabled_sz;
double last_statistics_reset_time; double last_statistics_reset_time;
...@@ -157,6 +163,8 @@ public: ...@@ -157,6 +163,8 @@ public:
vector<Tango::DevLong> statisticsTimeWindow; vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received. // ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay; Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
// Attribute data members // Attribute data members
public: public:
...@@ -175,6 +183,7 @@ public: ...@@ -175,6 +183,7 @@ public:
Tango::DevString *attr_alarmSummary_read; Tango::DevString *attr_alarmSummary_read;
Tango::DevString *attr_eventList_read; Tango::DevString *attr_eventList_read;
Tango::DevString *attr_eventSummary_read; Tango::DevString *attr_eventSummary_read;
Tango::DevString *attr_alarmDisabled_read;
// Constructors and destructors // Constructors and destructors
public: public:
...@@ -371,6 +380,15 @@ public: ...@@ -371,6 +380,15 @@ public:
*/ */
virtual void read_eventSummary(Tango::Attribute &attr); virtual void read_eventSummary(Tango::Attribute &attr);
virtual bool is_eventSummary_allowed(Tango::AttReqType type); virtual bool is_eventSummary_allowed(Tango::AttReqType type);
/**
* Attribute alarmDisabled related methods
* Description: List of alarms in out of service or shelved state
*
* Data type: Tango::DevString
* Attr type: Spectrum max = 10000
*/
virtual void read_alarmDisabled(Tango::Attribute &attr);
virtual bool is_alarmDisabled_allowed(Tango::AttReqType type);
// Dynamic attribute methods // Dynamic attribute methods
public: public:
...@@ -575,13 +593,13 @@ private: ...@@ -575,13 +593,13 @@ private:
void init_alarms(map< string,vector<string> > &alarm_events); void init_alarms(map< string,vector<string> > &alarm_events);
#endif #endif
void add_alarm(alarm_t& a, bool starting=false); void add_alarm(alarm_t& a, bool starting=false);
void add_event(alarm_t& a, vector<string> &evn) throw(string&); void add_event(alarm_t& a, vector<string> &evn);
#if 0 #if 0
void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn) throw(string&); void subscribe_event(alarm_t& a, EventCallBack& ecb, vector<string> &evn);
#endif #endif
// void do_alarm(bei_t& e); //gcc 4 problem?? // void do_alarm(bei_t& e); //gcc 4 problem??
bool remove_alarm(string& s) throw(string&); bool remove_alarm(string& s);
//void add_to_database(alarm_t& a) throw(string&); //void add_to_database(alarm_t& a);
void set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count=1); void set_internal_alarm(string name, Tango::TimeVal t, string msg, unsigned int count=1);
void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn); void load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn);
...@@ -589,7 +607,8 @@ private: ...@@ -589,7 +607,8 @@ private:
formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values); formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values);
void find_event_formula(tree_parse_info_t tree, vector<string> &); void find_event_formula(tree_parse_info_t tree, vector<string> &);
formula_res_t eval_expression(iter_t const& i, string &attr_values, int ev_ind=0); //recursive tree node evaluation formula_res_t eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind={}); //recursive tree node evaluation
void eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind);
void eval_node_event(iter_t const& i, vector<string> & ev); //recursive tree node evaluation void eval_node_event(iter_t const& i, vector<string> & ev); //recursive tree node evaluation
void prepare_alarm_attr(); //for read attribute alarm and push_change_event void prepare_alarm_attr(); //for read attribute alarm and push_change_event
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue> <DefaultPropValue>30</DefaultPropValue>
</classProperties> </classProperties>
<classProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</classProperties>
<deviceProperties name="GroupNames" description="Labels for Group mask, first is for mask 0x00"> <deviceProperties name="GroupNames" description="Labels for Group mask, first is for mask 0x00">
<type xsi:type="pogoDsl:StringVectorType"/> <type xsi:type="pogoDsl:StringVectorType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
...@@ -43,6 +48,11 @@ ...@@ -43,6 +48,11 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>30</DefaultPropValue> <DefaultPropValue>30</DefaultPropValue>
</deviceProperties> </deviceProperties>
<deviceProperties name="SetAlarmQuality" description="Set alarm attribute quality as computed using quality of attributes in the formula">
<type xsi:type="pogoDsl:BooleanType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>false</DefaultPropValue>
</deviceProperties>
<commands name="State" description="This command gets the device state (stored in its &lt;i>device_state&lt;/i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0"> <commands name="State" description="This command gets the device state (stored in its &lt;i>device_state&lt;/i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
<argin description="none."> <argin description="none.">
<type xsi:type="pogoDsl:VoidType"/> <type xsi:type="pogoDsl:VoidType"/>
...@@ -189,8 +199,8 @@ ...@@ -189,8 +199,8 @@
</commands> </commands>
<attributes name="alarmAudible" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> <attributes name="alarmAudible" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:BooleanType"/> <dataType xsi:type="pogoDsl:BooleanType"/>
<changeEvent fire="true" libCheckCriteria="false"/> <changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="false"/> <archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/> <dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="True if there is at least one alarm that needs audible indication on the GUI" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> <properties description="True if there is at least one alarm that needs audible indication on the GUI" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
...@@ -306,6 +316,14 @@ ...@@ -306,6 +316,14 @@
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes> </attributes>
<attributes name="alarmDisabled" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="10000" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="List of alarms in out of service or shelved state" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true"> <dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:EnumType"/> <dataType xsi:type="pogoDsl:EnumType"/>
<changeEvent fire="true" libCheckCriteria="true"/> <changeEvent fire="true" libCheckCriteria="true"/>
...@@ -324,8 +342,8 @@ ...@@ -324,8 +342,8 @@
</dynamicAttributes> </dynamicAttributes>
<dynamicAttributes name="AlarmFormula" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true"> <dynamicAttributes name="AlarmFormula" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
<dataType xsi:type="pogoDsl:StringType"/> <dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="true" libCheckCriteria="false"/> <changeEvent fire="true" libCheckCriteria="true"/>
<archiveEvent fire="true" libCheckCriteria="false"/> <archiveEvent fire="true" libCheckCriteria="true"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/> <dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
......
/*----- PROTECTED REGION ID(AlarmHandlerClass.cpp) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandlerClass.cpp) ENABLED START -----*/
static const char *RcsId = "$Id: $";
static const char *TagName = "$Name: $";
static const char *CvsPath = "$Source: $";
static const char *SvnPath = "$HeadURL: $";
static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc/ds_doc/";
//============================================================================= //=============================================================================
// //
// file : AlarmHandlerClass.cpp // file : AlarmHandlerClass.cpp
...@@ -78,7 +73,7 @@ AlarmHandlerClass *AlarmHandlerClass::_instance = NULL; ...@@ -78,7 +73,7 @@ AlarmHandlerClass *AlarmHandlerClass::_instance = NULL;
//-------------------------------------------------------- //--------------------------------------------------------
AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s) AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
{ {
cout2 << "Entering AlarmHandlerClass constructor" << endl; TANGO_LOG_INFO << "Entering AlarmHandlerClass constructor" << endl;
set_default_property(); set_default_property();
get_class_property(); get_class_property();
write_class_property(); write_class_property();
...@@ -87,7 +82,7 @@ AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s) ...@@ -87,7 +82,7 @@ AlarmHandlerClass::AlarmHandlerClass(string &s):Tango::DeviceClass(s)
/*----- PROTECTED REGION END -----*/ // AlarmHandlerClass::constructor /*----- PROTECTED REGION END -----*/ // AlarmHandlerClass::constructor
cout2 << "Leaving AlarmHandlerClass constructor" << endl; TANGO_LOG_INFO << "Leaving AlarmHandlerClass constructor" << endl;
} }
//-------------------------------------------------------- //--------------------------------------------------------
...@@ -167,7 +162,7 @@ AlarmHandlerClass *AlarmHandlerClass::instance() ...@@ -167,7 +162,7 @@ AlarmHandlerClass *AlarmHandlerClass::instance()
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "AckClass::execute(): arrived" << endl; TANGO_LOG_INFO << "AckClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin; const Tango::DevVarStringArray *argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->ack(argin)); ((static_cast<AlarmHandler *>(device))->ack(argin));
...@@ -187,7 +182,7 @@ CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_an ...@@ -187,7 +182,7 @@ CORBA::Any *AckClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_an
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "LoadClass::execute(): arrived" << endl; TANGO_LOG_INFO << "LoadClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->load(argin)); ((static_cast<AlarmHandler *>(device))->load(argin));
...@@ -207,7 +202,7 @@ CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_a ...@@ -207,7 +202,7 @@ CORBA::Any *LoadClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_a
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "RemoveClass::execute(): arrived" << endl; TANGO_LOG_INFO << "RemoveClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->remove(argin)); ((static_cast<AlarmHandler *>(device))->remove(argin));
...@@ -227,7 +222,7 @@ CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in ...@@ -227,7 +222,7 @@ CORBA::Any *RemoveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "SearchAlarmClass::execute(): arrived" << endl; TANGO_LOG_INFO << "SearchAlarmClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->search_alarm(argin)); return insert((static_cast<AlarmHandler *>(device))->search_alarm(argin));
...@@ -246,7 +241,7 @@ CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::An ...@@ -246,7 +241,7 @@ CORBA::Any *SearchAlarmClass::execute(Tango::DeviceImpl *device, const CORBA::An
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any)) CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{ {
cout2 << "StopAudibleClass::execute(): arrived" << endl; TANGO_LOG_INFO << "StopAudibleClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_audible()); ((static_cast<AlarmHandler *>(device))->stop_audible());
return new CORBA::Any(); return new CORBA::Any();
} }
...@@ -264,7 +259,7 @@ CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(co ...@@ -264,7 +259,7 @@ CORBA::Any *StopAudibleClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(co
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "SilenceClass::execute(): arrived" << endl; TANGO_LOG_INFO << "SilenceClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin; const Tango::DevVarStringArray *argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->silence(argin)); ((static_cast<AlarmHandler *>(device))->silence(argin));
...@@ -284,7 +279,7 @@ CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i ...@@ -284,7 +279,7 @@ CORBA::Any *SilenceClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "ModifyClass::execute(): arrived" << endl; TANGO_LOG_INFO << "ModifyClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->modify(argin)); ((static_cast<AlarmHandler *>(device))->modify(argin));
...@@ -304,7 +299,7 @@ CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in ...@@ -304,7 +299,7 @@ CORBA::Any *ModifyClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "ShelveClass::execute(): arrived" << endl; TANGO_LOG_INFO << "ShelveClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin; const Tango::DevVarStringArray *argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->shelve(argin)); ((static_cast<AlarmHandler *>(device))->shelve(argin));
...@@ -324,7 +319,7 @@ CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in ...@@ -324,7 +319,7 @@ CORBA::Any *ShelveClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "EnableClass::execute(): arrived" << endl; TANGO_LOG_INFO << "EnableClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->enable(argin)); ((static_cast<AlarmHandler *>(device))->enable(argin));
...@@ -344,7 +339,7 @@ CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in ...@@ -344,7 +339,7 @@ CORBA::Any *EnableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "DisableClass::execute(): arrived" << endl; TANGO_LOG_INFO << "DisableClass::execute(): arrived" << endl;
Tango::DevString argin; Tango::DevString argin;
extract(in_any, argin); extract(in_any, argin);
((static_cast<AlarmHandler *>(device))->disable(argin)); ((static_cast<AlarmHandler *>(device))->disable(argin));
...@@ -364,7 +359,7 @@ CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i ...@@ -364,7 +359,7 @@ CORBA::Any *DisableClass::execute(Tango::DeviceImpl *device, const CORBA::Any &i
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any)) CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{ {
cout2 << "ResetStatisticsClass::execute(): arrived" << endl; TANGO_LOG_INFO << "ResetStatisticsClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->reset_statistics()); ((static_cast<AlarmHandler *>(device))->reset_statistics());
return new CORBA::Any(); return new CORBA::Any();
} }
...@@ -382,7 +377,7 @@ CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSE ...@@ -382,7 +377,7 @@ CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSE
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any)) CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{ {
cout2 << "StopNewClass::execute(): arrived" << endl; TANGO_LOG_INFO << "StopNewClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->stop_new()); ((static_cast<AlarmHandler *>(device))->stop_new());
return new CORBA::Any(); return new CORBA::Any();
} }
...@@ -400,7 +395,7 @@ CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const ...@@ -400,7 +395,7 @@ CORBA::Any *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any) CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
{ {
cout2 << "GetAlarmInfoClass::execute(): arrived" << endl; TANGO_LOG_INFO << "GetAlarmInfoClass::execute(): arrived" << endl;
const Tango::DevVarStringArray *argin; const Tango::DevVarStringArray *argin;
extract(in_any, argin); extract(in_any, argin);
return insert((static_cast<AlarmHandler *>(device))->get_alarm_info(argin)); return insert((static_cast<AlarmHandler *>(device))->get_alarm_info(argin));
...@@ -419,7 +414,7 @@ CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::A ...@@ -419,7 +414,7 @@ CORBA::Any *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::A
//-------------------------------------------------------- //--------------------------------------------------------
CORBA::Any *ReLoadAllClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any)) CORBA::Any *ReLoadAllClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
{ {
cout2 << "ReLoadAllClass::execute(): arrived" << endl; TANGO_LOG_INFO << "ReLoadAllClass::execute(): arrived" << endl;
((static_cast<AlarmHandler *>(device))->re_load_all()); ((static_cast<AlarmHandler *>(device))->re_load_all());
return new CORBA::Any(); return new CORBA::Any();
} }
...@@ -491,6 +486,7 @@ void AlarmHandlerClass::get_class_property() ...@@ -491,6 +486,7 @@ void AlarmHandlerClass::get_class_property()
cl_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod")); cl_prop.push_back(Tango::DbDatum("SubscribeRetryPeriod"));
cl_prop.push_back(Tango::DbDatum("StatisticsTimeWindow")); cl_prop.push_back(Tango::DbDatum("StatisticsTimeWindow"));
cl_prop.push_back(Tango::DbDatum("ErrorDelay")); cl_prop.push_back(Tango::DbDatum("ErrorDelay"));
cl_prop.push_back(Tango::DbDatum("SetAlarmQuality"));
// Call database and extract values // Call database and extract values
if (Tango::Util::instance()->_UseDb==true) if (Tango::Util::instance()->_UseDb==true)
...@@ -546,6 +542,18 @@ void AlarmHandlerClass::get_class_property() ...@@ -546,6 +542,18 @@ void AlarmHandlerClass::get_class_property()
cl_prop[i] << errorDelay; cl_prop[i] << errorDelay;
} }
} }
// Try to extract SetAlarmQuality value
if (cl_prop[++i].is_empty()==false) cl_prop[i] >> setAlarmQuality;
else
{
// Check default value for SetAlarmQuality
def_prop = get_default_class_property(cl_prop[i].name);
if (def_prop.is_empty()==false)
{
def_prop >> setAlarmQuality;
cl_prop[i] << setAlarmQuality;
}
}
/*----- PROTECTED REGION ID(AlarmHandlerClass::get_class_property_after) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandlerClass::get_class_property_after) ENABLED START -----*/
// Check class property data members init // Check class property data members init
...@@ -624,6 +632,20 @@ void AlarmHandlerClass::set_default_property() ...@@ -624,6 +632,20 @@ void AlarmHandlerClass::set_default_property()
cl_def_prop.push_back(data); cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def); add_wiz_class_prop(prop_name, prop_desc, prop_def);
} }
else
add_wiz_class_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
cl_def_prop.push_back(data);
add_wiz_class_prop(prop_name, prop_desc, prop_def);
}
else else
add_wiz_class_prop(prop_name, prop_desc); add_wiz_class_prop(prop_name, prop_desc);
...@@ -683,6 +705,20 @@ void AlarmHandlerClass::set_default_property() ...@@ -683,6 +705,20 @@ void AlarmHandlerClass::set_default_property()
} }
else else
add_wiz_dev_prop(prop_name, prop_desc); add_wiz_dev_prop(prop_name, prop_desc);
prop_name = "SetAlarmQuality";
prop_desc = "Set alarm attribute quality as computed using quality of attributes in the formula";
prop_def = "false";
vect_data.clear();
vect_data.push_back("false");
if (prop_def.length()>0)
{
Tango::DbDatum data(prop_name);
data << vect_data ;
dev_def_prop.push_back(data);
add_wiz_dev_prop(prop_name, prop_desc, prop_def);
}
else
add_wiz_dev_prop(prop_name, prop_desc);
} }
//-------------------------------------------------------- //--------------------------------------------------------
...@@ -748,7 +784,7 @@ void AlarmHandlerClass::device_factory(const Tango::DevVarStringArray *devlist_p ...@@ -748,7 +784,7 @@ void AlarmHandlerClass::device_factory(const Tango::DevVarStringArray *devlist_p
// Create devices and add it into the device list // Create devices and add it into the device list
for (unsigned long i=0 ; i<devlist_ptr->length() ; i++) for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
{ {
cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl; TANGO_LOG_DEBUG << "Device name : " << (*devlist_ptr)[i].in() << endl;
device_list.push_back(new AlarmHandler(this, (*devlist_ptr)[i])); device_list.push_back(new AlarmHandler(this, (*devlist_ptr)[i]));
} }
...@@ -811,8 +847,8 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list) ...@@ -811,8 +847,8 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled // Not Polled
alarmaudible->set_disp_level(Tango::OPERATOR); alarmaudible->set_disp_level(Tango::OPERATOR);
// Not Memorized // Not Memorized
alarmaudible->set_change_event(true, false); alarmaudible->set_change_event(true, true);
alarmaudible->set_archive_event(true, false); alarmaudible->set_archive_event(true, true);
att_list.push_back(alarmaudible); att_list.push_back(alarmaudible);
// Attribute : StatisticsResetTime // Attribute : StatisticsResetTime
...@@ -1145,8 +1181,6 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list) ...@@ -1145,8 +1181,6 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled // Not Polled
eventlist->set_disp_level(Tango::OPERATOR); eventlist->set_disp_level(Tango::OPERATOR);
// Not Memorized // Not Memorized
//eventlist->set_change_event(true, true);
//eventlist->set_archive_event(true, true);
att_list.push_back(eventlist); att_list.push_back(eventlist);
// Attribute : eventSummary // Attribute : eventSummary
...@@ -1171,10 +1205,34 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list) ...@@ -1171,10 +1205,34 @@ void AlarmHandlerClass::attribute_factory(vector<Tango::Attr *> &att_list)
// Not Polled // Not Polled
eventsummary->set_disp_level(Tango::OPERATOR); eventsummary->set_disp_level(Tango::OPERATOR);
// Not Memorized // Not Memorized
//eventsummary->set_change_event(true, true);
//eventsummary->set_archive_event(true, true);
att_list.push_back(eventsummary); att_list.push_back(eventsummary);
// Attribute : alarmDisabled
alarmDisabledAttrib *alarmdisabled = new alarmDisabledAttrib();
Tango::UserDefaultAttrProp alarmdisabled_prop;
alarmdisabled_prop.set_description("List of alarms in out of service or shelved state");
// label not set for alarmDisabled
// unit not set for alarmDisabled
// standard_unit not set for alarmDisabled
// display_unit not set for alarmDisabled
// format not set for alarmDisabled
// max_value not set for alarmDisabled
// min_value not set for alarmDisabled
// max_alarm not set for alarmDisabled
// min_alarm not set for alarmDisabled
// max_warning not set for alarmDisabled
// min_warning not set for alarmDisabled
// delta_t not set for alarmDisabled
// delta_val not set for alarmDisabled
alarmdisabled->set_default_properties(alarmdisabled_prop);
// Not Polled
alarmdisabled->set_disp_level(Tango::OPERATOR);
// Not Memorized
alarmdisabled->set_change_event(true, true);
alarmdisabled->set_archive_event(true, true);
att_list.push_back(alarmdisabled);
// Create a list of static attributes // Create a list of static attributes
create_static_attribute_list(get_class_attr()->get_attr_list()); create_static_attribute_list(get_class_attr()->get_attr_list());
...@@ -1374,7 +1432,7 @@ void AlarmHandlerClass::create_static_attribute_list(vector<Tango::Attr *> &att_ ...@@ -1374,7 +1432,7 @@ void AlarmHandlerClass::create_static_attribute_list(vector<Tango::Attr *> &att_
defaultAttList.push_back(att_name); defaultAttList.push_back(att_name);
} }
cout2 << defaultAttList.size() << " attributes in default list" << endl; TANGO_LOG_INFO << defaultAttList.size() << " attributes in default list" << endl;
/*----- PROTECTED REGION ID(AlarmHandlerClass::create_static_att_list) ENABLED START -----*/ /*----- PROTECTED REGION ID(AlarmHandlerClass::create_static_att_list) ENABLED START -----*/
...@@ -1410,7 +1468,7 @@ void AlarmHandlerClass::erase_dynamic_attributes(const Tango::DevVarStringArray ...@@ -1410,7 +1468,7 @@ void AlarmHandlerClass::erase_dynamic_attributes(const Tango::DevVarStringArray
vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name); vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
if (ite_str == defaultAttList.end()) if (ite_str == defaultAttList.end())
{ {
cout2 << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl; TANGO_LOG_INFO << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << endl;
Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str()); Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str());
dev->remove_attribute(att_list[att.get_attr_idx()], true, false); dev->remove_attribute(att_list[att.get_attr_idx()], true, false);
--ite_att; --ite_att;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#ifndef AlarmHandlerClass_H #ifndef AlarmHandlerClass_H
#define AlarmHandlerClass_H #define AlarmHandlerClass_H
#include <tango.h> #include <tango/tango.h>
#include <AlarmHandler.h> #include <AlarmHandler.h>
...@@ -249,6 +249,19 @@ public: ...@@ -249,6 +249,19 @@ public:
{return (static_cast<AlarmHandler *>(dev))->is_eventSummary_allowed(ty);} {return (static_cast<AlarmHandler *>(dev))->is_eventSummary_allowed(ty);}
}; };
// Attribute alarmDisabled class definition
class alarmDisabledAttrib: public Tango::SpectrumAttr
{
public:
alarmDisabledAttrib():SpectrumAttr("alarmDisabled",
Tango::DEV_STRING, Tango::READ, 10000) {};
~alarmDisabledAttrib() {};
virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
{(static_cast<AlarmHandler *>(dev))->read_alarmDisabled(att);}
virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
{return (static_cast<AlarmHandler *>(dev))->is_alarmDisabled_allowed(ty);}
};
//========================================= //=========================================
// Define classes for dynamic attributes // Define classes for dynamic attributes
...@@ -633,6 +646,8 @@ class AlarmHandlerClass : public Tango::DeviceClass ...@@ -633,6 +646,8 @@ class AlarmHandlerClass : public Tango::DeviceClass
vector<Tango::DevLong> statisticsTimeWindow; vector<Tango::DevLong> statisticsTimeWindow;
// ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received. // ErrorDelay: Delay in seconds before changing to ERROR state after an exception is received.
Tango::DevULong errorDelay; Tango::DevULong errorDelay;
// SetAlarmQuality: Set alarm attribute quality as computed using quality of attributes in the formula
Tango::DevBoolean setAlarmQuality;
public: public:
// write class properties data members // write class properties data members
Tango::DbData cl_prop; Tango::DbData cl_prop;
......