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
Select Git revision
  • TANGOARCH-898
  • TANGOARCH-955
  • main
3 results

Target

Select target project
  • software-control-system/tango-controls-archiving/tango-controls-timeseries
1 result
Select Git revision
  • TANGOARCH-898
  • TANGOARCH-955
  • main
3 results
Show changes

Commits on Source 2

Showing
with 376 additions and 194 deletions
...@@ -145,17 +145,6 @@ ...@@ -145,17 +145,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>fr.soleil.lib</groupId>
<artifactId>hdbtdbArchivingApi</artifactId>
<exclusions>
<exclusion>
<artifactId>jdbi3-core</artifactId>
<groupId>org.jdbi</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>com.google.inject.extensions</groupId> <groupId>com.google.inject.extensions</groupId>
<artifactId>guice-grapher</artifactId> <artifactId>guice-grapher</artifactId>
......
...@@ -72,6 +72,7 @@ public class MySqlArchivingConfigWriter { ...@@ -72,6 +72,7 @@ public class MySqlArchivingConfigWriter {
logger.info(" attributeConfig = {}", attributeConfig); logger.info(" attributeConfig = {}", attributeConfig);
if (!idBefore.isPresent() || idBefore.getAsInt() <= 0) { if (!idBefore.isPresent() || idBefore.getAsInt() <= 0) {
// register new attribute // register new attribute
// TODO create table for attribute
logger.info("starting {} for the first time on {}", attributeName, archiverDeviceName); logger.info("starting {} for the first time on {}", attributeName, archiverDeviceName);
newId = OptionalInt.of(jdbi.withExtension(MySqlAttributeConfigCommands.class, dao -> dao.insert(attributeName, newId = OptionalInt.of(jdbi.withExtension(MySqlAttributeConfigCommands.class, dao -> dao.insert(attributeName,
attributeConfig.getType(), attributeConfig.getType(),
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
package fr.soleil.tango.archiving.config.db.mysql.tables; package fr.soleil.tango.archiving.config.db.mysql.tables;
import fr.soleil.tango.archiving.config.AttributeConfig; import fr.soleil.tango.archiving.config.AttributeConfig;
import fr.soleil.tango.archiving.config.db.mysql.utils.MySqlUtilities;
public class MySqlAttributeConfigMapper { public class MySqlAttributeConfigMapper {
...@@ -54,7 +55,10 @@ public class MySqlAttributeConfigMapper { ...@@ -54,7 +55,10 @@ public class MySqlAttributeConfigMapper {
config.setFormat(table.getFormat()); config.setFormat(table.getFormat());
config.setType(table.getType()); config.setType(table.getType());
config.setTime(table.getTime()); config.setTime(table.getTime());
config.setTableName(MySqlUtilities.getTableName(table.getAttConfId()));
} }
return config; return config;
} }
} }
/* /*
* Copyright (c) 2024. * Copyright (c) 2025.
* *
* Synchrotron Soleil * Synchrotron Soleil
* L'Orme des merisiers * L'Orme des merisiers
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* gwenaelle.abeille@synchrotron-soleil.fr * gwenaelle.abeille@synchrotron-soleil.fr
* *
* This software is a computer program whose purpose is to provide TANGO archived data through a GraphQL API. * This software is a computer program whose purpose is to provide an Java API for managing insertion and fetching of Tango data into a database
* *
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. * This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and * You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
...@@ -30,22 +30,21 @@ ...@@ -30,22 +30,21 @@
* terms. * terms.
*/ */
package fr.soleil.tango.archiving.infra.injection; package fr.soleil.tango.archiving.config.db.mysql.utils;
import com.google.inject.AbstractModule; public class MySqlUtilities {
import fr.soleil.database.connection.DataBaseParameters;
import fr.soleil.tango.archiving.event.db.legacy.insert.LegacyAttributeInserter;
import fr.soleil.tango.archiving.event.insert.IAttributeInserter;
public class LegacyModuleInjector extends AbstractModule { public static String getTableName(final int index) {
private final DataBaseParameters dataBaseParameters; String tableName = "att_";
if (index < 10) {
public LegacyModuleInjector(final DataBaseParameters dataBaseParameters) { tableName = tableName + "0000" + index;
this.dataBaseParameters = dataBaseParameters; } else if (index < 100) {
tableName = tableName + "000" + index;
} else if (index < 1000) {
tableName = tableName + "00" + index;
} else { // if (index < 10000) {
tableName = tableName + "0" + index;
} }
return tableName;
@Override
protected void configure() {
bind(IAttributeInserter.class).toInstance(new LegacyAttributeInserter(dataBaseParameters));
} }
} }
/*
* Copyright (c) 2024.
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* gwenaelle.abeille@synchrotron-soleil.fr
*
* This software is a computer program whose purpose is to provide TANGO archived data through a GraphQL API.
*
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
* INRIA at the following URL "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users
* are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive
* licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to
* manipulate, and that also therefore means that it is reserved for developers and experienced professionals having
* in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and
* operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its
* terms.
*/
package fr.soleil.tango.archiving.event.db.legacy.insert;
import com.google.inject.Inject;
import fr.esrf.Tango.AttrDataFormat;
import fr.esrf.Tango.AttrWriteType;
import fr.esrf.Tango.DevFailed;
import fr.soleil.archiving.common.api.ConnectionFactory;
import fr.soleil.archiving.common.api.exception.ArchivingException;
import fr.soleil.archiving.hdbtdb.api.management.attributes.adtapt.AdtAptAttributesFactory;
import fr.soleil.archiving.hdbtdb.api.management.attributes.adtapt.IAdtAptAttributes;
import fr.soleil.archiving.hdbtdb.api.management.attributes.hdb.insert.HdbAttributeInsertFactory;
import fr.soleil.archiving.hdbtdb.api.management.attributes.hdb.insert.IHdbAttributeInsert;
import fr.soleil.archiving.hdbtdb.api.tools.ScalarEvent;
import fr.soleil.archiving.hdbtdb.api.tools.SpectrumEvent_RO;
import fr.soleil.archiving.hdbtdb.api.tools.SpectrumEvent_RW;
import fr.soleil.database.connection.AbstractDataBaseConnector;
import fr.soleil.database.connection.DataBaseParameters;
import fr.soleil.tango.archiving.event.insert.AttributeEvent;
import fr.soleil.tango.archiving.event.insert.IAttributeInserter;
import fr.soleil.tango.archiving.exception.AttributeInsertionException;
import org.tango.attribute.AttributeTangoType;
import org.tango.utils.ArrayUtils;
@Deprecated
public class LegacyAttributeInserter implements IAttributeInserter {
private final IHdbAttributeInsert inserter;
@Inject
public LegacyAttributeInserter(DataBaseParameters params) {
try {
AbstractDataBaseConnector connector = ConnectionFactory.connect(params);
IAdtAptAttributes attributes = AdtAptAttributesFactory.getInstance(connector);
inserter = HdbAttributeInsertFactory.getInstance(connector, attributes);
} catch (ArchivingException e) {
throw new AttributeInsertionException(e);
}
}
@Override
public void insertScalar(AttributeEvent value, boolean withError) {
ScalarEvent event = new ScalarEvent();
event.setAttributeCompleteName(value.getFullName());
event.setTimeStamp(value.getDataTime().getTime());
event.setDataFormat(AttrDataFormat._SCALAR);
try {
event.setDataType(AttributeTangoType.getTypeFromClass(value.getValueR().getClass()).getTangoIDLType());
} catch (DevFailed devFailed) {
throw new AttributeInsertionException(devFailed);
}
if (value.getValueW() != null) {
Object val = new Object[]{value.getValueR(), value.getValueW()};
event.setValue(val, null);
event.setWritable(AttrWriteType._READ_WRITE);
} else {
event.setValue(value.getValueR(), null);
event.setWritable(AttrWriteType._READ);
}
try {
inserter.insert_ScalarData(event);
} catch (ArchivingException e) {
throw new AttributeInsertionException(e);
}
}
@Override
public void insertArray(AttributeEvent value, boolean withError) {
if (value.getValueW() == null) {
SpectrumEvent_RO spectrumEventRo = new SpectrumEvent_RO();
spectrumEventRo.setAttributeCompleteName(value.getFullName());
spectrumEventRo.setTimeStamp(value.getDataTime().getTime());
spectrumEventRo.setDataFormat(AttrDataFormat._SPECTRUM);
spectrumEventRo.setValue(value.getValueR(), null);
try {
spectrumEventRo.setDataType(AttributeTangoType.getTypeFromClass(value.getValueR().getClass()).getTangoIDLType());
} catch (DevFailed devFailed) {
throw new AttributeInsertionException(devFailed);
}
try {
inserter.insert_SpectrumData_RO(spectrumEventRo);
} catch (ArchivingException e) {
throw new AttributeInsertionException(e);
}
} else {
SpectrumEvent_RW spectrumEventRw = new SpectrumEvent_RW();
spectrumEventRw.setAttributeCompleteName(value.getFullName());
spectrumEventRw.setTimeStamp(value.getDataTime().getTime());
spectrumEventRw.setDataFormat(AttrDataFormat._SPECTRUM);
spectrumEventRw.setValue(ArrayUtils.addAll(value.getValueR(), value.getValueW()), null);
try {
spectrumEventRw.setDataType(AttributeTangoType.getTypeFromClass(value.getValueR().getClass()).getTangoIDLType());
} catch (DevFailed devFailed) {
throw new AttributeInsertionException(devFailed);
}
try {
inserter.insert_SpectrumData_RW(spectrumEventRw);
} catch (ArchivingException e) {
throw new AttributeInsertionException(e);
}
}
}
@Override
public void batchInsertScalar(String tableName, boolean withError, AttributeEvent... values) {
}
}
...@@ -54,15 +54,13 @@ public class MySqlAttributeInserter implements IAttributeInserter { ...@@ -54,15 +54,13 @@ public class MySqlAttributeInserter implements IAttributeInserter {
@Override @Override
public void insertScalar(AttributeEvent value, boolean withError) { public void insertScalar(AttributeEvent value, boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(value.getFullName()); AttributeConfig attributeConfigDB = config.getAttribute(value.getFullName());
System.out.println("attributeConfigDB " + attributeConfigDB);
int writeType = attributeConfigDB.getWriteType(); int writeType = attributeConfigDB.getWriteType();
MySqlAttributeEventScalarTable toInsert = buildAttributeEvent(writeType, value, attributeConfigDB); MySqlAttributeEventScalarTable toInsert = buildAttributeEvent(writeType, value, attributeConfigDB);
String tableName = getTableName(attributeConfigDB.getId()); logger.debug("inserting {} into {}", toInsert, attributeConfigDB.getTableName());
logger.debug("inserting {} into {}", toInsert, tableName);
if (writeType == AttrWriteType._READ_WRITE) { if (writeType == AttrWriteType._READ_WRITE) {
jdbi.useExtension(MySqlAttributeScalarCommands.class, dao -> dao.insertRW(tableName, toInsert)); jdbi.useExtension(MySqlAttributeScalarCommands.class, dao -> dao.insertRW(attributeConfigDB.getTableName(), toInsert));
} else { } else {
jdbi.useExtension(MySqlAttributeScalarCommands.class, dao -> dao.insert(tableName, toInsert)); jdbi.useExtension(MySqlAttributeScalarCommands.class, dao -> dao.insert(attributeConfigDB.getTableName(), toInsert));
} }
} }
...@@ -78,19 +76,6 @@ public class MySqlAttributeInserter implements IAttributeInserter { ...@@ -78,19 +76,6 @@ public class MySqlAttributeInserter implements IAttributeInserter {
return toInsert; return toInsert;
} }
public String getTableName(final int index) {
String tableName = "att_";
if (index < 10) {
tableName = tableName + "0000" + index;
} else if (index < 100) {
tableName = tableName + "000" + index;
} else if (index < 1000) {
tableName = tableName + "00" + index;
} else { // if (index < 10000) {
tableName = tableName + "0" + index;
}
return tableName;
}
@Override @Override
public void insertArray(AttributeEvent value, boolean withError) { public void insertArray(AttributeEvent value, boolean withError) {
......
/*
* Copyright (c) 2025.
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* gwenaelle.abeille@synchrotron-soleil.fr
*
* This software is a computer program whose purpose is to provide an Java API for managing insertion and fetching of Tango data into a database
*
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
* INRIA at the following URL "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users
* are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive
* licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to
* manipulate, and that also therefore means that it is reserved for developers and experienced professionals having
* in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and
* operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its
* terms.
*/
package fr.soleil.tango.archiving.event.db.mysql.select;
import com.google.inject.Inject;
import fr.soleil.tango.archiving.config.AttributeConfig;
import fr.soleil.tango.archiving.config.db.mysql.select.MySqlArchivingConfigFetcher;
import fr.soleil.tango.archiving.event.db.mysql.table.MySqlAttributeValueSeriesMapper;
import fr.soleil.tango.archiving.event.select.AttributeValue;
import fr.soleil.tango.archiving.event.select.AttributeValueSeries;
import fr.soleil.tango.archiving.event.select.IArchivingAttributeFetcher;
import fr.soleil.tango.archiving.exception.TangoTimeseriesException;
import org.jdbi.v3.core.Jdbi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Timestamp;
public class MySqArchivingAttributeFetcher implements IArchivingAttributeFetcher {
private final Logger logger = LoggerFactory.getLogger(MySqArchivingAttributeFetcher.class);
@Inject
private Jdbi jdbi;
@Inject
private MySqlArchivingConfigFetcher config;
@Override
public AttributeValueSeries getSince(final String attributeName, final Timestamp since, final boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) {
throw new TangoTimeseriesException(attributeName + " has never been stored");
}
AttributeValueSeries values = jdbi.withExtension(MySqlAttributeQueries.class, dao ->
MySqlAttributeValueSeriesMapper.getAttributeValueSeries(attributeConfigDB,
dao.selectSince(attributeConfigDB.getTableName(), since)));
logger.debug("got {} values since {}", values.getAttributeValues().size(), since);
return values;
}
@Override
public AttributeValue getLast(final String attributeName, final boolean withError) {
return null;
}
@Override
public AttributeValueSeries getBetween(final String attributeName, final Timestamp startTime, final Timestamp endTime, final boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) {
throw new TangoTimeseriesException(attributeName + " has never been stored");
}
AttributeValueSeries values = jdbi.withExtension(MySqlAttributeQueries.class, dao ->
MySqlAttributeValueSeriesMapper.getAttributeValueSeries(attributeConfigDB,
dao.selectBetween(attributeConfigDB.getTableName(), startTime, endTime))
);
logger.debug("got {} values between {}/{}", values.getAttributeValues().size(), startTime, endTime);
return values;
}
@Override
public AttributeValueSeries getWithSampling(final String attributeName, final String sampling, final String aggregateFunction, final Timestamp startTime, final Timestamp endTime) {
return null;
}
@Override
public AttributeValue getClosestValue(final String attributeName, final Timestamp timestamp, final boolean withError) {
return null;
}
@Override
public AttributeValue getAggregateValue(final String attributeName, final String aggregateFunction, final Timestamp from, final Timestamp to) {
return null;
}
}
/*
* Copyright (c) 2024.
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* gwenaelle.abeille@synchrotron-soleil.fr
*
* This software is a computer program whose purpose is to provide TANGO archived data through a GraphQL API.
*
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
* INRIA at the following URL "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users
* are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive
* licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to
* manipulate, and that also therefore means that it is reserved for developers and experienced professionals having
* in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and
* operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its
* terms.
*/
package fr.soleil.tango.archiving.event.db.mysql.select;
import fr.soleil.tango.archiving.event.db.mysql.table.MySqlAttributeEventScalarTable;
import org.jdbi.v3.sqlobject.config.RegisterFieldMapper;
import org.jdbi.v3.sqlobject.customizer.Bind;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import java.sql.Timestamp;
import java.util.List;
public interface MySqlAttributeQueries {
@SqlQuery("SELECT * FROM <tableName> WHERE time < :dataTime ORDER BY time")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
List<MySqlAttributeEventScalarTable> selectSince(@Define("tableName") String tableName, @Bind("dataTime") Timestamp dataTime);
@SqlQuery("select * from <tableName> WHERE time between :startTime and :endTime")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
List<MySqlAttributeEventScalarTable> selectBetween(@Define("tableName") String tableName,
@Bind("startTime") Timestamp startTime, @Bind("endTime") Timestamp endTime);
@SqlQuery("select att_conf_id, data_time, value_r, value_w, quality, att_error_desc_id, details " +
"from <tableName> where att_conf_id = :attConfID ORDER BY data_time DESC LIMIT 1")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
MySqlAttributeEventScalarTable selectLast(@Define("tableName") String tableName, @Bind("attConfID") int attConfID);
// SELECT time_bucket('30 minutes', data_time) AS bucket, avg(value_r) FROM att_scalar_devdouble
// WHERE att_conf_id = 1 GROUP BY bucket ORDER BY bucket ASC
@SqlQuery("SELECT time_bucket(<sampling>, data_time) AS bucket, " +
"<aggregateFunction>(value_r) AS value_r, <aggregateFunction>(value_w) AS value_w FROM <tableName> " +
"WHERE att_conf_id = :attConfID AND data_time > :startTime AND data_time < :endTime " +
"GROUP BY bucket ORDER BY bucket ASC")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
List<MySqlAttributeEventScalarTable> selectWithSampling(@Define("tableName") String tableName, @Bind("attConfID") int attConfID,
@Define("sampling") String sampling, @Define("aggregateFunction") String aggregateFunction,
@Bind("startTime") Timestamp startTime, @Bind("endTime") Timestamp endTime);
@SqlQuery("SELECT att_conf_id ,data_time, value_r, value_w, quality, details, att_error_desc_id FROM\n" +
"(\n" +
"(SELECT * FROM <tableName> WHERE data_time >= :attTimestamp and att_conf_id = :attConfID ORDER BY data_time LIMIT 1)\n" +
"UNION ALL\n" +
"(SELECT * FROM <tableName> WHERE data_time < :attTimestamp and att_conf_id = :attConfID ORDER BY data_time DESC LIMIT 1)\n" +
") as closest\n" +
" ORDER BY abs(extract(epoch from (data_time - :attTimestamp ))) LIMIT 1")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
MySqlAttributeEventScalarTable selectClosestValue(@Define("tableName") String tableName, @Bind("attConfID") int attributeID, @Bind("attTimestamp") Timestamp attTimestamp);
//select avg(value_r), avg(value_w) FROM att_scalar_devshort
// where att_conf_id = 1064 and data_time > '2022-03-27 16:40:46' AND data_time < '2023-03-27 16:40:46'
@SqlQuery("select <aggregateFunction>(value_r) as value_r, <aggregateFunction>(value_w) as value_w FROM <tableName>" +
" where att_conf_id = :attConfID and data_time > :startTime AND data_time < :endTime")
@RegisterFieldMapper(MySqlAttributeEventScalarTable.class)
MySqlAttributeEventScalarTable selectAggregateValue(
@Define("tableName") String tableName, @Define("aggregateFunction") String aggregateFunction,
@Bind("attConfID") int attributeID, @Bind("startTime") Timestamp startTime, @Bind("endTime") Timestamp endTime);
}
/*
* Copyright (c) 2024-2025.
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* gwenaelle.abeille@synchrotron-soleil.fr
*
* This software is a computer program whose purpose is to provide an Java API for managing insertion and fetching of Tango data into a database
*
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
* INRIA at the following URL "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users
* are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive
* licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to
* manipulate, and that also therefore means that it is reserved for developers and experienced professionals having
* in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and
* operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its
* terms.
*/
package fr.soleil.tango.archiving.event.db.mysql.table;
import fr.esrf.Tango.AttrWriteType;
import fr.soleil.tango.archiving.config.AttributeConfig;
import fr.soleil.tango.archiving.event.select.AttributeValue;
import fr.soleil.tango.archiving.event.select.AttributeValueSeries;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class MySqlAttributeValueSeriesMapper {
private final static Logger LOGGER = LoggerFactory.getLogger(MySqlAttributeValueSeriesMapper.class);
public static AttributeValueSeries getAttributeValueSeries(AttributeConfig attributeConfigDB, List<MySqlAttributeEventScalarTable> table) {
AttributeValueSeries valueSeries = new AttributeValueSeries();
valueSeries.setAttributeConfig(attributeConfigDB);
final List<AttributeValue> attributeValues = new ArrayList<>();
table.forEach(val -> attributeValues.add(MySqlAttributeValueSeriesMapper.getAttributeValue(val, attributeConfigDB.getWriteType())));
valueSeries.setAttributeValues(attributeValues);
return valueSeries;
}
public static AttributeValue getAttributeValue(MySqlAttributeEventScalarTable table, int writeType) {
AttributeValue value = new AttributeValue();
if (table != null) {
switch (writeType) {
case AttrWriteType._READ_WRITE:
Object readValue = table.getReadValue();
Object writeValue = table.getWriteValue();
LOGGER.debug("Value returned by db type is {}", readValue != null ? readValue.getClass().getCanonicalName() : "null");
value.setValueR(readValue);
value.setValueW(writeValue);
break;
case AttrWriteType._READ:
value.setValueR(table.getValue());
break;
case AttrWriteType._WRITE:
value.setValueW(table.getValue());
break;
}
value.setDataTime(table.getTime());
}
return value;
}
}
...@@ -36,8 +36,10 @@ import com.google.inject.Inject; ...@@ -36,8 +36,10 @@ import com.google.inject.Inject;
import fr.soleil.tango.archiving.config.AttributeConfig; import fr.soleil.tango.archiving.config.AttributeConfig;
import fr.soleil.tango.archiving.config.db.timescale.select.ArchivingConfigFetcher; import fr.soleil.tango.archiving.config.db.timescale.select.ArchivingConfigFetcher;
import fr.soleil.tango.archiving.event.db.timescale.tables.AttributeErrorTable; import fr.soleil.tango.archiving.event.db.timescale.tables.AttributeErrorTable;
import fr.soleil.tango.archiving.event.db.timescale.tables.AttributeValueSeriesMapper;
import fr.soleil.tango.archiving.event.select.AttributeValue; import fr.soleil.tango.archiving.event.select.AttributeValue;
import fr.soleil.tango.archiving.event.select.AttributeValueSeries; import fr.soleil.tango.archiving.event.select.AttributeValueSeries;
import fr.soleil.tango.archiving.event.select.IArchivingAttributeFetcher;
import fr.soleil.tango.archiving.exception.TangoTimeseriesException; import fr.soleil.tango.archiving.exception.TangoTimeseriesException;
import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.Jdbi;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -46,7 +48,7 @@ import org.slf4j.LoggerFactory; ...@@ -46,7 +48,7 @@ import org.slf4j.LoggerFactory;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Optional; import java.util.Optional;
public class ArchivingAttributeFetcher { public class ArchivingAttributeFetcher implements IArchivingAttributeFetcher {
private final Logger logger = LoggerFactory.getLogger(ArchivingAttributeFetcher.class); private final Logger logger = LoggerFactory.getLogger(ArchivingAttributeFetcher.class);
@Inject @Inject
...@@ -54,6 +56,7 @@ public class ArchivingAttributeFetcher { ...@@ -54,6 +56,7 @@ public class ArchivingAttributeFetcher {
@Inject @Inject
private ArchivingConfigFetcher config; private ArchivingConfigFetcher config;
@Override
public AttributeValueSeries getSince(String attributeName, Timestamp since, boolean withError) { public AttributeValueSeries getSince(String attributeName, Timestamp since, boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
...@@ -73,6 +76,7 @@ public class ArchivingAttributeFetcher { ...@@ -73,6 +76,7 @@ public class ArchivingAttributeFetcher {
return values; return values;
} }
@Override
public AttributeValue getLast(String attributeName, boolean withError) { public AttributeValue getLast(String attributeName, boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
...@@ -98,6 +102,7 @@ public class ArchivingAttributeFetcher { ...@@ -98,6 +102,7 @@ public class ArchivingAttributeFetcher {
} }
@Override
public AttributeValueSeries getBetween(String attributeName, Timestamp startTime, Timestamp endTime, boolean withError) { public AttributeValueSeries getBetween(String attributeName, Timestamp startTime, Timestamp endTime, boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
...@@ -119,6 +124,7 @@ public class ArchivingAttributeFetcher { ...@@ -119,6 +124,7 @@ public class ArchivingAttributeFetcher {
return values; return values;
} }
@Override
public AttributeValueSeries getWithSampling(String attributeName, String sampling, String aggregateFunction, Timestamp startTime, Timestamp endTime) { public AttributeValueSeries getWithSampling(String attributeName, String sampling, String aggregateFunction, Timestamp startTime, Timestamp endTime) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
...@@ -133,6 +139,7 @@ public class ArchivingAttributeFetcher { ...@@ -133,6 +139,7 @@ public class ArchivingAttributeFetcher {
return buckets; return buckets;
} }
@Override
public AttributeValue getClosestValue(String attributeName, Timestamp timestamp, boolean withError) { public AttributeValue getClosestValue(String attributeName, Timestamp timestamp, boolean withError) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
...@@ -148,6 +155,7 @@ public class ArchivingAttributeFetcher { ...@@ -148,6 +155,7 @@ public class ArchivingAttributeFetcher {
return table; return table;
} }
@Override
public AttributeValue getAggregateValue(String attributeName, String aggregateFunction, Timestamp from, Timestamp to) { public AttributeValue getAggregateValue(String attributeName, String aggregateFunction, Timestamp from, Timestamp to) {
AttributeConfig attributeConfigDB = config.getAttribute(attributeName); AttributeConfig attributeConfigDB = config.getAttribute(attributeName);
if (attributeConfigDB == null) { if (attributeConfigDB == null) {
......
/* /*
* Copyright (c) 2024. * Copyright (c) 2024-2025.
* *
* Synchrotron Soleil * Synchrotron Soleil
* L'Orme des merisiers * L'Orme des merisiers
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* gwenaelle.abeille@synchrotron-soleil.fr * gwenaelle.abeille@synchrotron-soleil.fr
* *
* This software is a computer program whose purpose is to provide TANGO archived data through a GraphQL API. * This software is a computer program whose purpose is to provide an Java API for managing insertion and fetching of Tango data into a database
* *
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. * This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and * You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
...@@ -30,10 +30,9 @@ ...@@ -30,10 +30,9 @@
* terms. * terms.
*/ */
package fr.soleil.tango.archiving.event.db.timescale.select; package fr.soleil.tango.archiving.event.db.timescale.tables;
import fr.soleil.tango.archiving.config.AttributeConfig; import fr.soleil.tango.archiving.config.AttributeConfig;
import fr.soleil.tango.archiving.event.db.timescale.tables.AttributeEventScalarTable;
import fr.soleil.tango.archiving.event.select.AttributeValue; import fr.soleil.tango.archiving.event.select.AttributeValue;
import fr.soleil.tango.archiving.event.select.AttributeValueSeries; import fr.soleil.tango.archiving.event.select.AttributeValueSeries;
import org.slf4j.Logger; import org.slf4j.Logger;
......
/*
* Copyright (c) 2025.
*
* Synchrotron Soleil
* L'Orme des merisiers
* Saint Aubin
* BP48
* 91192 GIF-SUR-YVETTE CEDEX
*
* gwenaelle.abeille@synchrotron-soleil.fr
*
* This software is a computer program whose purpose is to provide an Java API for managing insertion and fetching of Tango data into a database
*
* This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software.
* You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and
* INRIA at the following URL "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users
* are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive
* licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or
* reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to
* manipulate, and that also therefore means that it is reserved for developers and experienced professionals having
* in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and
* operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its
* terms.
*/
package fr.soleil.tango.archiving.event.select;
import java.sql.Timestamp;
public interface IArchivingAttributeFetcher {
AttributeValueSeries getSince(String attributeName, Timestamp since, boolean withError);
AttributeValue getLast(String attributeName, boolean withError);
AttributeValueSeries getBetween(String attributeName, Timestamp startTime, Timestamp endTime, boolean withError);
AttributeValueSeries getWithSampling(String attributeName, String sampling, String aggregateFunction, Timestamp startTime, Timestamp endTime);
AttributeValue getClosestValue(String attributeName, Timestamp timestamp, boolean withError);
AttributeValue getAggregateValue(String attributeName, String aggregateFunction, Timestamp from, Timestamp to);
}
...@@ -35,7 +35,9 @@ package fr.soleil.tango.archiving.infra.injection; ...@@ -35,7 +35,9 @@ package fr.soleil.tango.archiving.infra.injection;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import fr.soleil.tango.archiving.event.db.mysql.insert.MySqlAttributeInserter; import fr.soleil.tango.archiving.event.db.mysql.insert.MySqlAttributeInserter;
import fr.soleil.tango.archiving.event.db.mysql.select.MySqArchivingAttributeFetcher;
import fr.soleil.tango.archiving.event.insert.IAttributeInserter; import fr.soleil.tango.archiving.event.insert.IAttributeInserter;
import fr.soleil.tango.archiving.event.select.IArchivingAttributeFetcher;
import fr.soleil.tango.archiving.infra.db.DataSourceConnection; import fr.soleil.tango.archiving.infra.db.DataSourceConnection;
import fr.soleil.tango.archiving.infra.tango.ITangoAttributeCache; import fr.soleil.tango.archiving.infra.tango.ITangoAttributeCache;
import fr.soleil.tango.archiving.infra.tango.TangoAttributeCache; import fr.soleil.tango.archiving.infra.tango.TangoAttributeCache;
...@@ -58,8 +60,8 @@ public class MySqlDBModuleInjector extends AbstractModule { ...@@ -58,8 +60,8 @@ public class MySqlDBModuleInjector extends AbstractModule {
bind(ITangoAttributeCache.class).toInstance(new TangoAttributeCache()); bind(ITangoAttributeCache.class).toInstance(new TangoAttributeCache());
bind(IAttributeInserter.class).toInstance(new MySqlAttributeInserter()); bind(IAttributeInserter.class).toInstance(new MySqlAttributeInserter());
// TODO MariaDB implementations // TODO MariaDB implementations
// bind(ArchivingAttributeFetcher.class).toInstance(new ArchivingAttributeFetcher()); bind(IArchivingAttributeFetcher.class).toInstance(new MySqArchivingAttributeFetcher());
// bind(ArchivingConfigFetcher.class).toInstance(new ArchivingConfigFetcher()); // bind(IArchivingConfigFetcher.class).toInstance(new ArchivingConfigFetcher());
} }
......
...@@ -39,6 +39,7 @@ import fr.soleil.tango.archiving.config.select.IArchivingConfigFetcher; ...@@ -39,6 +39,7 @@ import fr.soleil.tango.archiving.config.select.IArchivingConfigFetcher;
import fr.soleil.tango.archiving.event.db.timescale.insert.AttributeInserter; import fr.soleil.tango.archiving.event.db.timescale.insert.AttributeInserter;
import fr.soleil.tango.archiving.event.db.timescale.select.ArchivingAttributeFetcher; import fr.soleil.tango.archiving.event.db.timescale.select.ArchivingAttributeFetcher;
import fr.soleil.tango.archiving.event.insert.IAttributeInserter; import fr.soleil.tango.archiving.event.insert.IAttributeInserter;
import fr.soleil.tango.archiving.event.select.IArchivingAttributeFetcher;
import fr.soleil.tango.archiving.infra.db.DataSourceConnection; import fr.soleil.tango.archiving.infra.db.DataSourceConnection;
import fr.soleil.tango.archiving.infra.tango.ITangoAttributeCache; import fr.soleil.tango.archiving.infra.tango.ITangoAttributeCache;
import fr.soleil.tango.archiving.infra.tango.TangoAttributeCache; import fr.soleil.tango.archiving.infra.tango.TangoAttributeCache;
...@@ -60,7 +61,7 @@ public class TimeScaleModuleInjector extends AbstractModule { ...@@ -60,7 +61,7 @@ public class TimeScaleModuleInjector extends AbstractModule {
bind(DataSourceConnection.class).toInstance(connection); bind(DataSourceConnection.class).toInstance(connection);
bind(IAttributeInserter.class).toInstance(new AttributeInserter()); bind(IAttributeInserter.class).toInstance(new AttributeInserter());
bind(ITangoAttributeCache.class).toInstance(new TangoAttributeCache()); bind(ITangoAttributeCache.class).toInstance(new TangoAttributeCache());
bind(ArchivingAttributeFetcher.class).toInstance(new ArchivingAttributeFetcher()); bind(IArchivingAttributeFetcher.class).toInstance(new ArchivingAttributeFetcher());
bind(IArchivingConfigFetcher.class).toInstance(new ArchivingConfigFetcher()); bind(IArchivingConfigFetcher.class).toInstance(new ArchivingConfigFetcher());
} }
......
...@@ -35,10 +35,10 @@ package fr.soleil.tango.archiving.services; ...@@ -35,10 +35,10 @@ package fr.soleil.tango.archiving.services;
import com.google.inject.Inject; import com.google.inject.Inject;
import fr.soleil.tango.archiving.config.AttributeParameters; import fr.soleil.tango.archiving.config.AttributeParameters;
import fr.soleil.tango.archiving.config.select.IArchivingConfigFetcher; import fr.soleil.tango.archiving.config.select.IArchivingConfigFetcher;
import fr.soleil.tango.archiving.event.db.timescale.select.ArchivingAttributeFetcher;
import fr.soleil.tango.archiving.event.insert.AttributeEvent; import fr.soleil.tango.archiving.event.insert.AttributeEvent;
import fr.soleil.tango.archiving.event.select.AttributeValue; import fr.soleil.tango.archiving.event.select.AttributeValue;
import fr.soleil.tango.archiving.event.select.AttributeValueSeries; import fr.soleil.tango.archiving.event.select.AttributeValueSeries;
import fr.soleil.tango.archiving.event.select.IArchivingAttributeFetcher;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Optional; import java.util.Optional;
...@@ -47,7 +47,7 @@ import java.util.OptionalInt; ...@@ -47,7 +47,7 @@ import java.util.OptionalInt;
public class TangoArchivingFetcherService { public class TangoArchivingFetcherService {
@Inject @Inject
private ArchivingAttributeFetcher archivingAttributeFetcher; private IArchivingAttributeFetcher archivingAttributeFetcher;
@Inject @Inject
private IArchivingConfigFetcher archivingConfigFetcher; private IArchivingConfigFetcher archivingConfigFetcher;
......