Skip to content
Snippets Groups Projects
Commit 40644a5c authored by Gwenaelle ABEILLE's avatar Gwenaelle ABEILLE
Browse files

Start migration to JTango

parent 4a478b13
No related branches found
No related tags found
No related merge requests found
package org.tango.archiving.server.manager;
import fr.esrf.Tango.DevFailed;
import fr.esrf.Tango.ErrSeverity;
import fr.soleil.archiving.common.api.ConnectionFactory;
import fr.soleil.archiving.common.api.exception.ArchivingException;
import fr.soleil.archiving.common.api.tools.GlobalConst;
import fr.soleil.archiving.hdbtdb.api.ConfigConst;
import fr.soleil.archiving.hdbtdb.api.HdbTdbConnectionParameters;
import fr.soleil.archiving.hdbtdb.api.manager.ArchivingManagerApiRefFactory;
import fr.soleil.archiving.hdbtdb.api.manager.IArchivingManagerApiRef;
import fr.soleil.archiving.hdbtdb.api.tools.ArchivingMessConfig;
import fr.soleil.archiving.hdbtdb.api.tools.mode.Mode;
import fr.soleil.database.connection.AbstractDataBaseConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tango.DeviceState;
import org.tango.server.ServerManager;
import org.tango.server.annotation.*;
import org.tango.utils.DevFailedUtils;
import java.util.Arrays;
import java.util.ResourceBundle;
/**
* Class Description: Device of Archiving system <Br>
* <Br>
* <br>
* <b>ROLE</b><br>
* This DeviceServer is used in order to manage the archiving of exported Tango
* attributes device. <Br>
* <Br>
* <br>
* <b>ARCHIVING TYPE</b><br>
* There is two kind of archiving : <Br>
* <Br>
* <Li><b>The Historical archiving</b>, manage by HdbArchiver devices.<br>
* This kind archiving allows to store in a database all the exported tango attributes.<br>
* It is a continuous and never deleted storage.<br>
* The frequency use for this kind of storage is usually small. <Br>
* <Br> <Li><b>The Temporary archiving</b>, manage by TdbArchiver devices.<br>
* This kind archiving allows to store in a database all the exported tango attributes.<br>
* The stored values are kept in the database for a limited time ("Keeping Window" [4 hours - 24 hours]). Before being
* stored into the database, values are first collected into files (timestamp, read value [, write value]). Those files
* are periodically exported to the database. This export frequency must also be given ("Export Window" [5 seconds - 1
* hour]).<br>
* The frequency use for this kind of storage is usually high. <Br>
* <Br>
* <br>
* <b>ARCHIVING MODE</b><br>
* An archiving sequence must be tuned to follow one (or several) of the defined archiving modes :<br> <Li>The
* <b>Periodical mode</b>, this mode allows to archive following a defined frequency.<br> <Li>The <b>Absolute mode</b>,
* this mode allows to archive a value only if : <br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &gt; <var>previous_archived_value</var> +
* <var>&delta;<sub>1</sub></var> &nbsp;&nbsp;&nbsp;&nbsp; or <br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &lt; <var>previous_archived_value</var> -
* <var>&delta;<sub>2</sub></var>.<br> <Li>The <b>Relative mode</b>, this mode allows to archive a value only if :<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &gt; <var>previous_archived_value</var>
* <var>&micro;<sub>increase</sub></var> &nbsp;&nbsp;&nbsp;&nbsp; or <br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &lt; <var>previous_archived_value</var>
* <var>&micro;<sub>decrease</sub></var>.<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<var>&micro;<sub>increase</sub></var> and
* <var>&micro;<sub>decrease</sub></var> are percentages) <Li>The <b>Threshold mode</b>, this mode allows to archive a
* value only if :<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &gt;
* <var>threshold_value<sub>sup</sub></var> &nbsp;&nbsp;&nbsp;&nbsp; or <br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <var>current_value</var> &lt;
* <var>threshold_value<sub>min</sub></var>.<br>
* (like alarms work).<br>
* <Br>
* <Br> <Li>The <b>On Calculation mode</b>, this mode allows to archive according to a user formula.<br> <Li>The <b>On
* Difference mode</b>, this mode allows to archive when a value changes.<br> <Li>The <b>External mode</b>, this mode
* allows to archive on the user demand.<br>
* <br>
* <br>
* The 6 last mode must be associated to a periodic mode. <Br>
* <Br>
*
* @author $Author: pierrejoseph $
* @version $Revision: 1.19 $
*/
@Device
public class ArchivingManager {
private Logger logger = LoggerFactory.getLogger(ArchivingManager.class);
private IArchivingManagerApiRef hdbManager, tdbManager;
/**
* Computer identifier on wich is settled the database DB. The identifier
* can be the computer name or its IP address. <br>
* <b>Default value : </b> hdb
*/
@DeviceProperty
private String hdbHost;
/**
* Database name.<br>
* <b>Default value : </b> hdb
*/
@DeviceProperty
private String hdbName;
/**
* Computer identifier on wich is settled the database TDB. The identifier
* can be the computer name or its IP address. <br>
* <b>Default value : </b> tdb
*/
@DeviceProperty
private String tdbHost;
/**
* Database name.<br>
* <b>Default value : </b> tdb
*/
@DeviceProperty
private String tdbName;
/**
* User identifier (name) used to connect the historical database.
*/
@DeviceProperty
private String hdbUser;
/**
* Password used to connect the historical database.
*/
@DeviceProperty
private String hdbPassword;
/**
* User identifier (name) used to connect the temporary database.
*/
@DeviceProperty
private String tdbUser;
/**
* Password used to connect the temporary database.
*/
@DeviceProperty
private String tdbPassword;
/**
* true if the ORACLE RAC connection is activated. This information is
* appended to all device's (or attributes) name. false otherwise.<br>
* <b>Default value : </b> false
*/
@DeviceProperty
private boolean hdbRacConnection;
@DeviceProperty
private boolean tdbRacConnection;
@DeviceProperty
private String hdbSchema;
@DeviceProperty
private String tdbSchema;
@State
private DeviceState state;
@Status
private String status;
private static String VERSION;
public static void main(final String[] args) {
VERSION = ResourceBundle.getBundle("application").getString("project.version");
ServerManager.getInstance().start(args, ArchivingManager.class);
}
@Attribute
public String getVersion() {
return VERSION;
}
public DeviceState getState() {
return state;
}
public void setState(DeviceState state) {
this.state = state;
}
private void connectHdb() throws DevFailed {
AbstractDataBaseConnector hdbConnector = ConnectionFactory.connectThroughTango("HdbManager",
ConfigConst.HDB_CLASS_DEVICE, hdbHost, hdbName, hdbSchema, hdbUser, hdbPassword, null, null,
hdbRacConnection, false, true);
hdbManager = ArchivingManagerApiRefFactory.getInstance(true, hdbConnector);
try {
hdbManager.archivingConfigure();
} catch (ArchivingException e) {
throw e.toTangoException();
}
}
protected void connectTdb() throws DevFailed {
AbstractDataBaseConnector tdbConnector = ConnectionFactory.connectThroughTango("TdbManager",
ConfigConst.TDB_CLASS_DEVICE, tdbHost, tdbName, tdbSchema, tdbUser, tdbPassword, null, null,
tdbRacConnection, false, true);
tdbManager = ArchivingManagerApiRefFactory.getInstance(false, tdbConnector);
try {
tdbManager.archivingConfigure();
} catch (ArchivingException e) {
throw e.toTangoException();
}
}
private void connect() {
boolean isHdbOK;
StringBuilder statusBuilder = new StringBuilder();
try {
connectHdb();
isHdbOK = true;
} catch (DevFailed e) {
isHdbOK = false;
statusBuilder.append("HDB connection failed: ").append(DevFailedUtils.toString(e)).append("\n");
}
System.out.println("connect HDB "+isHdbOK );
boolean isTdbOK;
try {
connectTdb();
isTdbOK = true;
} catch (DevFailed e) {
isTdbOK = false;
statusBuilder.append("TDB connection failed: ").append(DevFailedUtils.toString(e)).append("\n");
}
System.out.println("connect TDB "+isTdbOK );
if (!isHdbOK || !isTdbOK) {
state = DeviceState.ALARM;
} else {
state = DeviceState.ON;
System.out.println(hdbManager);
System.out.println(tdbManager);
statusBuilder.append("HDB Archivers: ").append(Arrays.toString(hdbManager.getMExportedArchiverList()))
.append("\n");
statusBuilder.append("TDB Archivers: ").append(Arrays.toString(tdbManager.getMExportedArchiverList()))
.append("\n");
}
status = statusBuilder.toString();
}
@Init
public void init() throws DevFailed, ArchivingException {
HdbTdbConnectionParameters.initDbAvailable();
connect();
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
/**
* Execute command "ArchivingConfigure" on device. This command configures
* the connection to the historical and temporary databases. It then needs 4
* parameters : a login and password for Hdb + a login and password for Tdb
*
* @param argin <ul>
* <li><var>argin</var>[<code>0</code>], the <em>user name</em> used to logg into the historical
* database.
* <li><var>argin</var>[<code>1</code>], the <em>password</em> used to logg into the historical database.
* <li><var>argin</var>[<code>2</code>], the <em>user name</em> used to logg into the temporary database.
* <li><var>argin</var>[<code>9</code>], the <em>password</em> used to logg into the temporary database.
* </ul>
*/
@Command(name = "ArchivingConfigure")
public void archivingConfigure(final String[] argin) throws DevFailed {
logger.info("Entering archiving_configure()");
String exitMessage = "Exiting archiving_configure()";
if ((argin == null) || (argin.length < 4)) {
String errorMessage = "Invalid argument";
logger.warn(errorMessage);
logger.info(exitMessage);
throw new DevFailed(errorMessage, null);
} else {
// ---Add your Own code to control device here ---
/*
* try { ArchivingManagerApi.ArchivingConfigure(argin[ 0 ] , argin[ 1 ]
* , argin[ 2 ] , argin[ 3 ], argin[ 4 ]); } catch ( ArchivingException
* e ) { get_logger().warn(e.toString() , e); throw
* e.toTangoException(); }
*/
boolean needsToThrow = false;
// TODO maybe update status, and maybe avoid connections to undesired database (HdbTdbConnectionParameters)
ArchivingException hdbArchivingException = null;
IArchivingManagerApiRef previousHdbManager = hdbManager;
try {
String hdbUser = argin[0], hdbPassword = argin[1];
AbstractDataBaseConnector hdbConnector = ConnectionFactory.connectThroughTango("HdbManager",
ConfigConst.HDB_CLASS_DEVICE, hdbHost, hdbName, hdbSchema, hdbUser, hdbPassword, null, null,
hdbRacConnection, false, true);
hdbManager = ArchivingManagerApiRefFactory.getInstance(true, hdbConnector);
hdbManager.archivingConfigure();
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
// throw e.toTangoException(); CLA 30/10/06 AN EXCEPTION IS NO
// LONGER THROWN, AS BOTH DATABASES ARE INITIALIZED INDEPENDENTLY
hdbArchivingException = e;
needsToThrow = true;
// restore previous manager as this one does not seem to be ok
hdbManager = previousHdbManager;
} catch (DevFailed e) {
logger.warn(DevFailedUtils.toString(e), e);
hdbArchivingException = new ArchivingException(e);
needsToThrow = true;
// restore previous manager as this one does not seem to be ok
hdbManager = previousHdbManager;
}
ArchivingException tdbArchivingException = null;
IArchivingManagerApiRef previousTdbManager = tdbManager;
try {
String tdbUser = argin[2], tdbPassword = argin[3];
AbstractDataBaseConnector tdbConnector = ConnectionFactory.connectThroughTango("TdbManager",
ConfigConst.TDB_CLASS_DEVICE, tdbHost, tdbName, tdbSchema, tdbUser, tdbPassword, null, null,
tdbRacConnection, false, false);
tdbManager = ArchivingManagerApiRefFactory.getInstance(true, tdbConnector);
tdbManager.archivingConfigure();
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
// throw e.toTangoException(); CLA 30/10/06 AN EXCEPTION IS NO
// LONGER THROWN, AS BOTH DATABASES ARE INITIALIZED INDEPENDENTLY
tdbArchivingException = e;
needsToThrow = true;
// restore previous manager as this one does not seem to be ok
tdbManager = previousTdbManager;
} catch (DevFailed e) {
logger.warn(DevFailedUtils.toString(e), e);
tdbArchivingException = new ArchivingException(e);
needsToThrow = true;
// restore previous manager as this one does not seem to be ok
tdbManager = previousTdbManager;
}
/*
* if ( hdbArchivingException != null ) { String desc =
* "Failed connecting to HDB"; ArchivingException exceptionHDB = new
* ArchivingException (message , reason , ErrSeverity.PANIC , desc , ""
* ); totale.addStack ( desc, exceptionHDB ); } if (
* tdbArchivingException != null ) { String desc =
* "Failed connecting to TDB"; ArchivingException exceptionTDB = new
* ArchivingException (message , reason , ErrSeverity.PANIC , desc , ""
* ); totale.addStack ( desc, exceptionTDB ); }
*/
String desc;
if (hdbArchivingException != null) {
if (tdbArchivingException != null) {
desc = "Failed connecting to HDB and TDB";
} else {
desc = "Failed connecting to HDB";
}
} else if (tdbArchivingException != null) {
desc = "Failed connecting to TDB";
} else {
desc = "";
}
logger.info(exitMessage);
if (needsToThrow) {
final String reason = "Failed while executing ArchivingManager.archiving_configure() method...";
final String message = GlobalConst.ARCHIVING_ERROR_PREFIX + " : ";
final ArchivingException e = new ArchivingException(message, reason, ErrSeverity.PANIC, desc, "");
throw e.toTangoException();
}
}
}
/**
* Execute command "ArchivingStartHdb" on device. Start an historical
* archiving for the specified attributes, and following the specified mode.
*
* @param argin Archiving arguments... <BR>
* <blockquote>
* <ul>
* <li><strong>The first part :</strong>
* <ul>
* <li><var>argin</var>[0]<b> =</b> the load balancing type of the archiving<br>
* &quot;1&quot;, if all the attribute are archived together in the same HdbArchiver device, <br>
* &quot;0&quot; otherwise.
* <li><var>argin</var>[1]<b> =</b> the number of attributes to archive<br>
* <li><var>argin</var>[2] to <var>argin</var> [2 + <var>argin</var>[1] - 1] = the name of each attribute
* </ul>
* <li><strong>The second part (the <i>Mode </i>part) :</strong> <br>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 2]).
* <ul>
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_P</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_A</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the delta value max when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_R</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_T</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the smallest value (min) when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_C</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)
* <br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>number of values</i> taken into account<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>type </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 5] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_D</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* </ul>
* </ul>
* </blockquote>
* @see fr.soleil.archiving.hdbtdb.api.tools.ArchivingMessConfig
*/
@Command(name = "ArchivingStartHdb")
public void archivingStartHdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_start_hdb()");
if (hdbManager == null) {
connectHdb();
}
if (hdbManager != null) {
try {
final ArchivingMessConfig archivingMessConfig = ArchivingMessConfig
.creationWithoutFullInformation(argin);
hdbManager.archivingStart(archivingMessConfig);
} catch (Exception e) {
if (e instanceof DevFailed) {
throw (DevFailed) e;
} else if (e instanceof ArchivingException) {
ArchivingException ae = (ArchivingException) e;
ae.printStackTrace();
logger.warn(ae.toString(), ae);
throw ae.toTangoException();
} else {
logger.error("unexpected error on hdb archiving start", e);
}
}
}
logger.info("Exiting archiving_start_hdb()");
}
/**
* Execute command "ArchivingStartTdb" on device. Start an temporary
* archiving for the specified attributes, and following the specified mode.
*
* @param argin Archiving arguments... <BR>
* <blockquote>
* <ul>
* <li><strong>The first part :</strong>
* <ul>
* <li><var>argin</var>[0]<b> =</b> the load balancing type of the archiving<br>
* &quot;1&quot;, if all the attribute are archived together in the same HdbArchiver device, <br>
* &quot;0&quot; otherwise.
* <li><var>argin</var>[1]<b> =</b> the number of attributes to archive<br>
* <li><var>argin</var>[2] to <var>argin</var> [2 + <var>argin</var>[1] - 1] = the name of each attribute
* </ul>
* <li><strong>The second part (the <i>Mode </i>part) :</strong> <br>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 2]).
* <ul>
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_P</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_A</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the delta value max when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_R</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_T</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the smallest value (min) when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_C</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)
* <br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>number of values</i> taken into account<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>type </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 5] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_D</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* <li><strong>The Temporary (<i>Intermediate Archiving</i>) archiving specific informations </strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>TDB_SPEC</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>export frequency </i>(ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>keeping window duration </i>in (ms)<br>
* <var>index</var> = <var>index</var> + 3<br>
* </ul>
* </ul>
* </blockquote>
* @see fr.soleil.archiving.hdbtdb.api.tools.ArchivingMessConfig
*/
@Command(name = "ArchivingStartTdb")
public void archivingStartTdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_start_tdb()");
if (tdbManager == null) {
connectTdb();
}
final ArchivingMessConfig archivingMessConfig = ArchivingMessConfig.creationWithoutFullInformation(argin);
try {
tdbManager.archivingStart(archivingMessConfig);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
logger.info("Exiting archiving_start_tdb()");
}
/**
* Execute command "ArchivingStopHdb" on device. Stops the historical
* archiving for the given attributes.
*
* @param argin The attribute list.
*/
@Command(name = "ArchivingStopHdb")
public void archivingStopHdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_stop_hdb()");
if (hdbManager == null) {
connectHdb();
}
try {
hdbManager.archivingStopConf(argin);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
}
/**
* Execute command "ArchivingStopTdb" on device. Stops the temporary
* archiving for the given attributes.
*
* @param argin The attribute list.
*/
@Command(name = "ArchivingStopTdb")
public void archivingStopTdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_stop_tdb()");
if (tdbManager == null) {
connectTdb();
}
try {
tdbManager.archivingStopConf(argin);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
logger.info("Exiting archiving_stop_tdb()");
}
/**
* Execute command "ArchivingModifHdb" on device. Change the mode of an
* historical archiving.
*
* @param argin The configuration to switch to... <br>
* <blockquote>
* <ul>
* <li><strong>The first part :</strong>
* <ul>
* <li><var>argin</var>[0]<b> =</b> the load balancing type of the archiving<br>
* &quot;1&quot;, if all the attribute are archived together in the same TdbArchiver device, <br>
* &quot;0&quot; otherwise.
* <li><var>argin</var>[1]<b> =</b> the number of attributes to archive<br>
* <li><var>argin</var>[2] to <var>argin</var> [2 + <var>argin</var>[1] - 1] = the name of each attribute
* </ul>
* <li><strong>The second part (the <i>Mode </i>part) :</strong> <br>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 2]).
* <ul>
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_P</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_A</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the delta value max when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_R</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_T</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the smallest value (min) when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_C</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)
* <br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>number of values</i> taken into account<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>type </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 5] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_D</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* </ul>
* </ul>
* </blockquote>
* @see fr.soleil.archiving.hdbtdb.api.tools.ArchivingMessConfig
*/
@Command(name = "ArchivingModifHdb")
public void archivingModifHdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_modif_hdb()");
if (hdbManager == null) {
connectHdb();
}
final ArchivingMessConfig archivingMessConfig = ArchivingMessConfig.creationWithoutFullInformation(argin);
try {
hdbManager.archivingStopConf(archivingMessConfig.getAttributeList());
archivingStartHdb(argin);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
logger.info("Exiting archiving_modif_hdb()");
}
/**
* Execute command "ArchivingModifTdb" on device. Change the mode of a
* temporary archiving.
*
* @param argin The configuration to switch to...... <br>
* <blockquote>
* <ul>
* <li><strong>The first part :</strong>
* <ul>
* <li><var>argin</var>[0]<b> =</b> the load balancing type of the archiving<br>
* &quot;1&quot;, if all the attribute are archived together in the same TdbArchiver device, <br>
* &quot;0&quot; otherwise.
* <li><var>argin</var>[1]<b> =</b> the number of attributes to archive<br>
* <li><var>argin</var>[2] to <var>argin</var> [2 + <var>argin</var>[1] - 1] = the name of each attribute
* </ul>
* <li><strong>The second part (the <i>Mode </i>part) :</strong> <br>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 2]).
* <ul>
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_P</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_A</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the delta value max when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_R</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_T</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the smallest value (min) when decreasing<br>
* <var>argin</var>[<var>index</var>+ 4] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_C</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)
* <br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>number of values</i> taken into account<br>
* <var>argin</var>[<var>index</var>+ 4] = the <i>type </i>associated to this mode<br>
* <var>argin</var>[<var>index</var>+ 5] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_D</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* <li><strong>The Temporary (<i>Intermediate Archiving</i>) archiving specific informations </strong><br>
* <var>argin</var>[<var>index</var>+ 1] = <code>TDB_SPEC</code><br>
* <var>argin</var>[<var>index</var>+ 2] = the <i>export frequency </i>(ms)<br>
* <var>argin</var>[<var>index</var>+ 3] = the <i>keeping window duration </i>in (ms)<br>
* <var>index</var> = <var>index</var> + 3<br>
* </ul>
* </ul>
* </blockquote>
* @see fr.soleil.archiving.hdbtdb.api.tools.ArchivingMessConfig
*/
@Command(name = "ArchivingModifTdb")
public void archivingModifTdb(final String[] argin) throws DevFailed {
logger.info("Entering archiving_modif_tdb()");
if (tdbManager == null) {
connectTdb();
}
final ArchivingMessConfig archivingMessConfig = ArchivingMessConfig.creationWithoutFullInformation(argin);
try {
tdbManager.archivingStopConf(archivingMessConfig.getAttributeList());
archivingStartTdb(argin);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
logger.info("Exiting archiving_modif_tdb()");
}
/**
* Execute command "IsArchivedHdb" on device. Check the archiving state
* (historical archiving) for each attribute of the given list.
*
* @param argin The attribute list.
* @return For each attribute of the given list...<br>
* <ul>
* <li><code>1</code>, if the attribute is currently being archived (historical archiving)
* <li><code>0</code>, otherwise
* </ul>
*/
@Command(name = "IsArchivedHdb")
public short[] isArchivedHdb(final String[] argin) throws DevFailed {
logger.info("Entering is_archived_hdb()");
if (hdbManager == null) {
connectHdb();
}
short[] argout = new short[argin.length];
boolean result = false;
for (int i = 0; i < argin.length; i++) {
try {
result = hdbManager.isArchived(argin[i]);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
if (result) {
argout[i] = 1;
} else {
argout[i] = 0;
}
}
logger.info("Exiting is_archived_hdb()");
return argout;
}
/**
* Execute command "IsArchivedTdb" on device. Check the archiving state
* (temporary archiving) for each attribute of the given list.
*
* @param argin The attribute list.
* @return For each attribute of the given list...<br>
* <ul>
* <li><code>1</code>, if the attribute is currently being archived (temporary archiving)
* <li><code>0</code>, otherwise
* </ul>
*/
@Command(name = "IsArchivedTdb")
public short[] isArchivedTdb(final String[] argin) throws DevFailed {
logger.info("Entering is_archived_tdb()");
short[] argout = new short[argin.length];
if (tdbManager == null) {
connectTdb();
}
boolean result = false;
for (int i = 0; i < argin.length; i++) {
try {
result = tdbManager.isArchived(argin[i]);
} catch (final ArchivingException e) {
logger.warn(e.toString(), e);
throw e.toTangoException();
}
if (result) {
argout[i] = 1;
} else {
argout[i] = 0;
}
}
logger.info("Exiting is_archived_tdb()");
return argout;
}
/**
* Execute command "GetArchivingModeHdb" on device. Return the historical
* archiving mode applied to an attribute.
*
* @param argin The attribute name.
* @return The applied mode... <br>
* <blockquote>
* <ul>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 0]).
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_P</code><br>
* <var>argout</var>[<var>index</var> + 1] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_A</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the delta value max when decreasing<br>
* <var>argout</var>[<var>index</var>+ 3] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_R</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argout</var>[<var>index</var>+ 3] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_T</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the smallest value (min) when decreasing<br>
* <var>argout</var>[<var>index</var>+ 3] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_C</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the <i>number of values</i> taken into account<br>
* <var>argout</var>[<var>index</var>+ 3] = the <i>type </i>associated to this mode<br>
* <var>argout</var>[<var>index</var>+ 4] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_D</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* </ul>
* </blockquote>
*/
@Command(name = "GetArchivingModeHdb")
public String[] getArchivingModeHdb(final String argin) throws DevFailed {
logger.info("Entering get_archiving_mode_hdb()");
if (hdbManager == null) {
connectHdb();
}
String[] argout;
try {
final Mode mode = hdbManager.getArchivingMode(argin);
argout = mode.toArray();
} catch (final ArchivingException e) {
logger.error(e.getMessage());
throw e.toTangoException();
}
logger.info("Exiting get_archiving_mode_hdb()");
return argout;
}
/**
* Execute command "GetArchivingModeTdb" on device. Return the temporary
* archiving mode applied to an attribute.
*
* @param argin The attribute name.
* @return The applied mode... <br>
* <blockquote>
* <ul>
* Let us note <i>&quot;<var>index</var>&quot; </i>the last <var>index</var> used (for example, at this
* point, <i><var>index</var></i> = 0]).
* <li><strong>If the Mode is composed of a <i>Periodical Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_P</code><br>
* <var>argout</var>[<var>index</var> + 1] = the period of the periodic mode in (ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>Absolute Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_A</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the frequency of the <i>absolute mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the delta value max when decreasing<br>
* <var>argout</var>[<var>index</var>+ 3] = the delta value max when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of a <i>Relative Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_R</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of the <i>relative mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the <i>decreasing variation </i>associated to this mode<br>
* <var>argout</var>[<var>index</var>+ 3] = the <i>increasing variation </i>associated to this mode<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li><strong>If the Mode is composed of an <i>Threshold Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_T</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the frequency of the <i>threshold mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the smallest value (min) when decreasing<br>
* <var>argout</var>[<var>index</var>+ 3] = the biggest value (max) when increasing<br>
* <var>index</var> = <var>index</var> + 4<br>
* <li>If the Mode is composed of a <i>On Calculation Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_C</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of the <i>on calculation mode </i>in (ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the <i>number of values</i> taken into account<br>
* <var>argout</var>[<var>index</var>+ 3] = the <i>type </i>associated to this mode<br>
* <var>argout</var>[<var>index</var>+ 4] = Not used at the moment <br>
* <var>index</var> = <var>index</var> + 5<br>
* <li><strong>If the Mode is composed of an <i>On Difference Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_D</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>frequency </i>of this<i> mode </i>(in ms)<br>
* <var>index</var> = <var>index</var> + 2<br>
* <li><strong>If the Mode is composed of an <i>External Mode</i></strong><br>
* <var>argout</var>[<var>index</var>] = <code>MODE_E</code><br>
* <var>index</var> = <var>index</var> + 1<br>
* <li><strong>The Temporary (<i>Intermediate Archiving</i>) archiving specific informations </strong><br>
* <var>argout</var>[<var>index</var>] = <code>TDB_SPEC</code><br>
* <var>argout</var>[<var>index</var>+ 1] = the <i>export frequency </i>(ms)<br>
* <var>argout</var>[<var>index</var>+ 2] = the <i>keeping window duration </i>in (ms)<br>
* <var>index</var> = <var>index</var> + 3<br>
* </ul>
* </blockquote>
*/
@Command(name = "GetArchivingModeTdb")
public String[] getArchivingModeTdb(final String argin) throws DevFailed {
logger.info("Entering get_archiving_mode_tdb()");
String[] argout;
if (tdbManager == null) {
connectTdb();
}
try {
final Mode mode = tdbManager.getArchivingMode(argin);
argout = mode.toArray();
} catch (final ArchivingException e) {
logger.error(e.getMessage());
throw e.toTangoException();
}
logger.info("Exiting get_archiving_mode_tdb()");
return argout;
}
/**
* Execute command "GetStatusHdb" on device. For each attribute of the given
* list, get the status of the device in charge of its historical archiving
*
* @param argin The attribute list.
* @return The list of status.
*/
@Command(name = "GetStatusHdb")
public String[] getStatusHdb(final String[] argin) throws DevFailed {
logger.info("Entering get_status_hdb()");
if (hdbManager == null) {
connectHdb();
}
String[] argout = new String[argin.length];
for (int i = 0; i < argin.length; i++) {
try {
argout[i] = hdbManager.getStatus(argin[i]);
} catch (final ArchivingException e) {
throw e.toTangoException();
}
}
logger.info("Exiting get_status_hdb()");
return argout;
}
/**
* Execute command "GetStatusTdb" on device. For each attribute of the given
* list, get the status of the device in charge of its temporary archiving.
*
* @param argin The attribute list.
* @return The list of status.
*/
@Command(name = "GetStatusTdb")
public String[] getStatusTdb(final String[] argin) throws DevFailed {
logger.info("Entering get_status_tdb()");
String[] argout = new String[argin.length];
if (tdbManager == null) {
connectTdb();
}
for (int i = 0; i < argin.length; i++) {
try {
argout[i] = tdbManager.getStatus(argin[i]);
} catch (final ArchivingException e) {
throw e.toTangoException();
}
}
logger.info("Exiting get_status_tdb()");
return argout;
}
public void setHdbHost(String hdbHost) {
this.hdbHost = hdbHost;
}
public void setHdbName(String hdbName) {
this.hdbName = hdbName;
}
public void setTdbHost(String tdbHost) {
this.tdbHost = tdbHost;
}
public void setTdbName(String tdbName) {
this.tdbName = tdbName;
}
public void setHdbUser(String hdbUser) {
this.hdbUser = hdbUser;
}
public void setHdbPassword(String hdbPassword) {
this.hdbPassword = hdbPassword;
}
public void setTdbUser(String tdbUser) {
this.tdbUser = tdbUser;
}
public void setTdbPassword(String tdbPassword) {
this.tdbPassword = tdbPassword;
}
public void setHdbRacConnection(boolean hdbRacConnection) {
this.hdbRacConnection = hdbRacConnection;
}
public void setTdbRacConnection(boolean tdbRacConnection) {
this.tdbRacConnection = tdbRacConnection;
}
public void setHdbSchema(String hdbSchema) {
this.hdbSchema = hdbSchema;
}
public void setTdbSchema(String tdbSchema) {
this.tdbSchema = tdbSchema;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment