Commit 0e3f10aa authored by Pascal Verdier's avatar Pascal Verdier
Browse files

Imported from SVN

parents
.idea
target
# Changelog
#### HdbConfiguratorServer-1.5 - 28/08/17:
Manage strategy (default contexts) when adding attributes
#### HdbConfiguratorServer-1.4 - 22/03/17:
Checked with multiple TANGO_HOST
#### HdbConfiguratorServer-1.3 - 08/02/17:
Compatibility with HdbConfigurator 2.0 and higher
#### HdbConfiguratorServer-1.2 - 06/06/16:
RemoveAttributes command added.
#### HdbConfiguratorServer-1.1 - 27/05/16:
A thread to execute the subscriptions later added.
#### HdbConfiguratorServer-1.0 - 13/05/16:
Initial revision
# Project HdbConfiguratorServer
Maven Java project
This class is able to use HdbConfigurator classes to
Add/Start/Stop archiving attributes on HDB++ subscribers.
It is mainly used to do it from device servers.
## Cloning
```
git clone git@gitlab.esrf.fr:accelerators/System/HdbConfiguratorServer
```
## Building and Installation
### Dependencies
The project has the following dependencies.
#### Project Dependencies
* hdbpp-configurator.jar
* JTango.jar
#### Toolchain Dependencies
* javac 7 or higher
* maven
### Build Flags
Custom build flags for the project device server:
| Flag | Default | Use |
|------|---------|-----|
|FLAG|STATE|DESCRIPTION|
### Build
Instructions on building the project.
```
cd HdbConfiguratorServer
mvn package
```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.tango.server</groupId>
<artifactId>HdbConfiguratorServer</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>HdbConfiguratorServer Tango server</name>
<developers>
<developer>
<name>verdier</name>
<email>accelerator-control@esrf.fr</email>
<organizationUrl>ESRF</organizationUrl>
<roles>
<role>Developer</role>
</roles>
</developer>
</developers>
<scm>
<connection>scm:git:git@gitlab.esrf.fr:Accelerators/System/HdbConfiguratorServer.git</connection>
<developerConnection>scm:git:git@gitlab.esrf.fr:Accelerators/System/HdbConfiguratorServer</developerConnection>
<url>https://gitlab.esrf.fr/Accelerators/System/HdbConfiguratorServer</url>
<tag>HEAD</tag>
</scm>
<dependencies>
<dependency>
<groupId>org.tango</groupId>
<artifactId>JTangoServer</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.tango.hdb</groupId>
<artifactId>hdbpp-configurator</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.tango.hdbconfiguratorserver.HdbConfiguratorServer</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="ASCII"?>
<pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl">
<classes name="HdbConfiguratorServer" pogoRevision="9.6">
<description description="This class is able to use HdbConfigurator classes to Add/Start/Stop&#xA;archiving attributes on HDB++ subscribers.&#xA;It uses call on HdbConfiguratorServer device." title="HDB++ manager" sourcePath="/mntdirect/_segfs/tango/tmp/pascal/dev/servers/HdbConfiguratorServer/src/main/java" language="Java" filestogenerate="XMI file,Protected Regions,pom.xml" license="GPL" copyright="Copyright (C): 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016&#xA; European Synchrotron Radiation Facility&#xA; BP 220, Grenoble 38043&#xA; France" hasMandatoryProperty="true" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false">
<inheritances classname="Device_Impl" sourcePath=""/>
<identification contact="at esrf.fr - accelerator-control" author="accelerator-control" emailDomain="esrf.fr" classFamily="System" siteSpecific="" platform="All Platforms" bus="Not Applicable" manufacturer="none" reference="">
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
<keyWords>Archiving</keyWords>
</identification>
</description>
<deviceProperties name="HdbManager" mandatory="true" description="The HDB++ manager device name (HdbConfiguratorServer class).&#xA;This property is mandatory">
<type xsi:type="pogoDsl:StringType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</deviceProperties>
<deviceProperties name="WaitingTime" description="Waiting time before trying to add attributes to HDB++ in seconds">
<type xsi:type="pogoDsl:IntType"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<DefaultPropValue>10</DefaultPropValue>
</deviceProperties>
<commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
<argin description="none">
<type xsi:type="pogoDsl:VoidType"/>
</argin>
<argout description="Device state">
<type xsi:type="pogoDsl:StateType"/>
</argout>
<status abstract="true" inherited="true" concrete="true"/>
</commands>
<commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0">
<argin description="none">
<type xsi:type="pogoDsl:VoidType"/>
</argin>
<argout description="Device status">
<type xsi:type="pogoDsl:ConstStringType"/>
</argout>
<status abstract="true" inherited="true" concrete="true"/>
</commands>
<commands name="AddAttributes" description="Add specified attributes to the specified subscriber attribute list&#xA;if not already done and start archiving.&#xA;Due to a possible dead lock, during this command execution and&#xA;the event subscribing, this subscription will delayed and done by a thread.&#xA;To avoid a bottle neck for this command execution, the subscriptions&#xA;will be serialized. That means that it could takes several seconds.&#xA;Use AddingState and AddingStatus commands to know if subscriptions&#xA;are done without problem." execMethod="add_attributes" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="[0] - Subscriber name.&#xA;[1] - Attribute 1 name.&#xA;[2] - Attribute 2 name.&#xA; - - - - - &#xA;[n] - Attribute n name.&#xA;[n+1] - true/false for using push event (false if not specified)">
<type xsi:type="pogoDsl:StringArrayType"/>
</argin>
<argout description="ID number. Usefull to get information later.">
<type xsi:type="pogoDsl:IntType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AddingState" description="Returns the AddingAttributes command state." execMethod="adding_state" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="ID returns by AddAttributes command">
<type xsi:type="pogoDsl:IntType"/>
</argin>
<argout description="ON if adding has been done.&#xA;ALARM if at least one have failed.&#xA;MOVING if adding is not finished.">
<type xsi:type="pogoDsl:StateType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AddingStatus" description="Returns the AddingAttributes command status." execMethod="adding_status" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="ID returns by AddAttributes command">
<type xsi:type="pogoDsl:IntType"/>
</argin>
<argout description="Return AddAttributes command error message if any.">
<type xsi:type="pogoDsl:StringType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributeIsManaged" description="Check if the specified attribute is managed by a subscriber.&#xA;If not, use AddAttributes command to set it managed." execMethod="attribute_is_managed" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Attribute name">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="true if attribute managed. False otherwise.">
<type xsi:type="pogoDsl:BooleanType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributeStarted" description="Check if attribute archiving is started" execMethod="attribute_started" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Specified attribute name.">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="true if archiving is started">
<type xsi:type="pogoDsl:BooleanType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributePaused" description="Check if attribute archiving is paused" execMethod="attribute_paused" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Specified attribute name.">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="true if archiving is paused">
<type xsi:type="pogoDsl:BooleanType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributeStopped" description="Check if attribute archiving is stopped" execMethod="attribute_stopped" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Specified attribute name.">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="true if archiving is stopped">
<type xsi:type="pogoDsl:BooleanType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributeGetArchiver" description="Returns the subscriber name for specified attribute." execMethod="attribute_get_archiver" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Specified attriute name.">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="The subscriber name.">
<type xsi:type="pogoDsl:StringType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="AttributeGetArchiverAlias" description="Returns the subscriber alias for specified attribute." execMethod="attribute_get_archiver_alias" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Specified attriute alias.">
<type xsi:type="pogoDsl:StringType"/>
</argin>
<argout description="The subscriber name.">
<type xsi:type="pogoDsl:StringType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="StartArchiving" description="Start archiving for specified attributes." execMethod="start_archiving" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Attribute names to be started.">
<type xsi:type="pogoDsl:StringArrayType"/>
</argin>
<argout description="">
<type xsi:type="pogoDsl:VoidType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="StopArchiving" description="Stop archiving for specified attributes." execMethod="stop_archiving" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Attribute names to be stopped.">
<type xsi:type="pogoDsl:StringArrayType"/>
</argin>
<argout description="">
<type xsi:type="pogoDsl:VoidType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<commands name="RemoveAttributes" description="Stop archiving if necessary and remove attributes from subscriber list" execMethod="remove_attributes" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
<argin description="Attribute list to be removed">
<type xsi:type="pogoDsl:StringArrayType"/>
</argin>
<argout description="">
<type xsi:type="pogoDsl:VoidType"/>
</argout>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</commands>
<attributes name="HdbManagerDeviceName" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="false" libCheckCriteria="false"/>
<archiveEvent fire="false" libCheckCriteria="false"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="Returns the manager device name" label="HDB manager device name" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<attributes name="ArchiverList" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="1000" maxX="0" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="false" libCheckCriteria="false"/>
<archiveEvent fire="false" libCheckCriteria="false"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="Managed archiver list" label="Archiver list" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<attributes name="ArchiverAliasList" attType="Spectrum" rwType="READ" displayLevel="OPERATOR" polledPeriod="1000" maxX="0" maxY="" allocReadMember="true" isDynamic="false">
<dataType xsi:type="pogoDsl:StringType"/>
<changeEvent fire="false" libCheckCriteria="false"/>
<archiveEvent fire="false" libCheckCriteria="false"/>
<dataReadyEvent fire="false" libCheckCriteria="true"/>
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
<properties description="Managed archiver alias list" label="Archiver Alias list" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
</attributes>
<states name="ON" description="Every thing is OK.">
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</states>
<states name="UNKNOWN" description="The HdbManager device is not responding.">
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</states>
<states name="ALARM" description="The HdbManger device ALARM.&#xA;At least one subscriber is in ALARM.">
<status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
</states>
<preferences docHome="./doc_html" makefileHome="/segfs/tango/cppserver/env"/>
</classes>
</pogoDsl:PogoSystem>
//+======================================================================
// : $
//
// Project: Tango
//
// Description: java source code for Tango manager tool..
//
// : pascal_verdier $
//
// Copyright (C) : 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This file is part of Tango.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Tango is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Tango. If not, see <http://www.gnu.org/licenses/>.
//
// : $
//
//-======================================================================
package org.tango.hdbconfiguratorserver;
import fr.esrf.Tango.DevFailed;
import fr.esrf.Tango.DevState;
import fr.esrf.TangoApi.DeviceProxy;
import fr.esrf.TangoDs.Except;
import org.tango.hdb_configurator.common.HdbAttribute;
import org.tango.hdb_configurator.common.Strategy;
import org.tango.hdb_configurator.configurator.ManageAttributes;
import java.util.ArrayList;
import java.util.List;
/**
* This class is a list of configuration object
* and manage thread in charge to execute
* serialized configurations
*
* @author verdier
*/
public class ConfigurationExecution {
private DeviceProxy managerProxy;
private long waitBeforeStart;
private ConfigurationThread thread;
private List<ConfigurationObject> configurationToDoList = new ArrayList<>();
private List<ConfigurationObject> configurationDoneList = new ArrayList<>();
private final Object monitor = new Object();
private static final long CONFIG_AGE_MAX = 5*60*1000;
//===============================================================
//===============================================================
public ConfigurationExecution(DeviceProxy managerProxy, long waitBeforeStart) {
this.managerProxy = managerProxy;
this.waitBeforeStart = waitBeforeStart;
thread = new ConfigurationThread();
thread.start();
}
//===============================================================
//===============================================================
public void addConfiguration(ConfigurationObject configurationObject) {
synchronized (monitor) {
configurationToDoList.add(configurationObject);
Utils.traceExecution("addConfiguration()");
thread.wakeUp();
}
}
//===============================================================
//===============================================================
private ConfigurationObject getConfiguration(int index, List<ConfigurationObject> list) {
synchronized (monitor) {
return list.get(index);
}
}
//===============================================================
//===============================================================
private void removeFirst(List<ConfigurationObject> list) {
synchronized (monitor) {
list.remove(0);
}
}
//===============================================================
//===============================================================
public String getAddingError(int id) throws DevFailed {
// Check in Done list
String error = "No Error";
for (int i=0 ; i<configurationDoneList.size() ; i++) {
ConfigurationObject configuration = getConfiguration(i, configurationDoneList);
if (configuration.getConfID()==id) {
if (configuration.hasFailed())
error = configuration.getError();
}
}
return error;
}
//===============================================================
//===============================================================
public DevState addingState(int id) throws DevFailed {
// Check if ToDo list
for (int i=0 ; i<configurationToDoList.size() ; i++) {
if (getConfiguration(i, configurationToDoList).getConfID() == id)
return DevState.MOVING;
}
// Check in Done list
for (int i=0 ; i<configurationDoneList.size() ; i++) {
ConfigurationObject configuration = getConfiguration(i, configurationDoneList);
if (configuration.getConfID()==id) {
if (configuration.hasFailed())
return DevState.ALARM;
else
return DevState.ON;
}
}
System.err.println("-------> ID=" + id + " not found in list");
Except.throw_exception("IdNotFound", "ID=" + id + " not found in list");
return null; // never occur after throwing DevFailed
}
//===============================================================
//===============================================================
//===============================================================
/**
* A thread to manage execution
*/
//===============================================================
private class ConfigurationThread extends Thread {
private boolean runThread = true;
//===========================================================
public void run() {
while (runThread) {
Utils.traceExecution("Thread running");
while (!configurationToDoList.isEmpty()) {
// Do execution and move object from ToDo to Done list
ConfigurationObject configuration = getConfiguration(0, configurationToDoList);
doExecution(configuration);
configurationDoneList.add(configuration);
removeFirst(configurationToDoList);
}
runMyGarbageCollector();
nextLoop();
}
}
//===========================================================
private void runMyGarbageCollector() {
// Check if ConfigurationObjects done are so old to be removed
int nbToRemove = 0;
for (ConfigurationObject configuration : configurationDoneList) {
long age = System.currentTimeMillis() - configuration.getCreationTime();
if (age>=CONFIG_AGE_MAX)
nbToRemove++;
else
break; // after they are younger
}
for (int i=0 ; i<nbToRemove ; i++) {
Utils.traceExecution("removing idx=" + i);
removeFirst(configurationDoneList);
}
}
//===========================================================
private void doExecution(ConfigurationObject configuration) {
Utils.traceExecution("doExecution for id = " + configuration.getConfID());
waitBeforeStart(configuration);
Utils.traceExecution("check configuration");
if (configuration.initializeAttributes(managerProxy)) {
Utils.traceExecution("Do the configuration");
addAttributes(configuration);
startArchiving(configuration);
Utils.traceExecution("Configuration done for ID=" + configuration.getConfID());
}
}
//===========================================================
private void addAttributes(ConfigurationObject configuration) {
try {
// Create a hdb attribute list from configuration
List<HdbAttribute> hdbAttributes = new ArrayList<>();
List<String> attributeNames = configuration.getAttributeToAdd();
Strategy strategy = configuration.getStrategy();
boolean pushedByCode = configuration.isPushedByCode();
for (String attributeName : attributeNames) {
Utils.traceExecution(attributeName);
hdbAttributes.add(new HdbAttribute(attributeName, strategy, pushedByCode));
}
ManageAttributes.addAttributes(managerProxy, configuration.getSubscriberName(), hdbAttributes);
}
catch (DevFailed e) {
configuration.setError(managerProxy.name()+": "+e.errors[0].desc);
}
}
//===========================================================
private void startArchiving(ConfigurationObject configuration) {
List<String> attributeNames = configuration.getAttributeToStart();
for (String attributeName : attributeNames){
try {
Utils.startAttribute(attributeName, managerProxy);
}
catch (DevFailed e) {
configuration.setError(e.errors[0].desc);
}
}
}
//===========================================================
private void waitBeforeStart(ConfigurationObject configuration) {
long timeToWait = waitBeforeStart -
(System.currentTimeMillis() - configuration.getCreationTime());
// Check if must wait a bit ?
if (timeToWait>0) {
Utils.traceExecution("Sleeping " + timeToWait + " ms");
try { sleep(timeToWait); } catch (InterruptedException e) { /* */ }
}
else
Utils.traceExecution("No sleep (" + timeToWait + ")");
}
//===========================================================
private synchronized void nextLoop() {
try { wait(CONFIG_AGE_MAX); } catch (InterruptedException e) { /* */ }
}
//===========================================================
private synchronized void wakeUp() {
notify();
}
//===========================================================
}
//===============================================================
//===============================================================
}