blob: 8a749d87d8b01d7c98e5152912794020cd307e6f [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2020 Eclipse APP4MC contributors.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************
*/
package org.eclipse.app4mc.atdb;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.PrimitiveIterator.OfLong;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public class ATDBConnection extends DBConnection<ATDBConnection> {
private static final String EC = "EC";
// query statements
private static final String METAINFORMATION_QUERY = "SELECT value FROM metaInformation WHERE name = ?;";
private static final String ENTITY_BY_TYPE_QUERY = "SELECT name FROM entity WHERE entityTypeId = (SELECT id FROM entityType WHERE entityType.name = ?);";
private static final String ENTITY_INSTANCES_QUERY = "SELECT sqcnr FROM entityInstance WHERE entityId = (SELECT id FROM entity WHERE name = ?);";
private static final String EVENTS_QUERY = "SELECT event.name FROM event;";
private static final String EVENT_BY_TYPE_QUERY = EVENTS_QUERY.substring(0, EVENTS_QUERY.length() - 1)
+ " WHERE eventTypeId = (SELECT id FROM eventType WHERE eventType.name = ?);";
private static final String EVENT_BY_ENTITY_TYPE_QUERY = EVENTS_QUERY.substring(0, EVENTS_QUERY.length() - 1) + ", entity "
+ "WHERE event.entityId = entity.id AND entity.entityTypeId = (SELECT id FROM entityType WHERE entityType.name = ?);";
private static final String EVENT_TYPE_OF_EVENT_QUERY = "SELECT eventType.name FROM event, eventType "
+ "WHERE event.eventTypeId = eventType.id AND event.name = ?;";
private static final String ENTITY_OF_EVENT_QUERY = "SELECT entity.name FROM event, entity "
+ "WHERE event.entityId = entity.id AND event.name = ?;";
private static final String SOURCE_ENTITY_OF_EVENT_QUERY = "SELECT entity.name FROM event, entity "
+ "WHERE event.sourceEntityId = entity.id AND event.name = ?;";
private static final String ENTITY_PROPERTY_ENTITYREF_QUERY = "SELECT (SELECT name FROM entity WHERE id = value) AS entities "
+ "FROM entity AS sourceEntity, propertyValue WHERE sourceEntity.name = ? "
+ "AND entityTypeId = (SELECT id FROM entityType WHERE entityType.name = ?) "
+ "AND propertyValue.entityId = sourceEntity.id "
+ "AND propertyValue.propertyId = (SELECT id FROM property WHERE name = ?);";
private static final String ENTITY_PROPERTY_VALUE_QUERY = "SELECT propertyValue.value "
+ "FROM entity AS sourceEntity, propertyValue WHERE sourceEntity.name = ? "
+ "AND entityTypeId = (SELECT id FROM entityType WHERE entityType.name = ?) "
+ "AND propertyValue.entityId = sourceEntity.id "
+ "AND propertyValue.propertyId = (SELECT id FROM property WHERE name = ?);";
private static final String EVENTCHAIN_EVENTREF_QUERY = "SELECT (SELECT GROUP_CONCAT((SELECT name FROM event WHERE id = value), ', ') "
+ "FROM propertyValue WHERE entityId = ecEntity.id AND propertyId = (SELECT id FROM property WHERE name = ?)) AS evName "
+ "FROM entity AS ecEntity WHERE ecEntity.name = ? AND entityTypeId = (SELECT id FROM entityType WHERE entityType.name = '" + EC + "');";
private static final String METRICS_QUERY = "SELECT name FROM metric;";
private static final String METRICVALUE_QUERY = "SELECT value FROM entityMetricValue WHERE entityId = (SELECT id FROM entity WHERE name = ?) "
+ "AND metricId = (SELECT id FROM metric WHERE name = ?);";
// insert statements
private static final String METAINFORMATION_INSERT = "INSERT OR IGNORE INTO metaInformation VALUES(?, ?);";
private static final String ENTITYTYPE_INSERT = "INSERT OR IGNORE INTO entityType(name) VALUES(?);";
private static final String ENTITY_INSERT = "INSERT OR IGNORE INTO entity(name, entityTypeId) VALUES(?, (SELECT id FROM entityType WHERE name = ?));";
private static final String ENTITY_INSERT_WITH_TYPE_ID = "INSERT OR IGNORE INTO entity(name, entityTypeId) VALUES(?, ?);";
private static final String ENTITYINSTANCE_INSERT = "INSERT OR IGNORE INTO entityInstance VALUES((SELECT id FROM entity WHERE name = ?), ?);";
private static final String EVENTTYPE_INSERT = "INSERT OR IGNORE INTO eventType(name) VALUES(?);";
private static final String EVENT_INSERT = "INSERT OR IGNORE INTO event(name, eventTypeId, entityId, sourceEntityId) "//
+ "VALUES(?, (SELECT id FROM eventType WHERE name = ?), (SELECT id FROM entity WHERE name = ?), (SELECT id FROM entity WHERE name = ?));";
private static final String METRIC_INSERT = "INSERT OR IGNORE INTO metric(name, dimension) VALUES(?, ?);";
private static final String ENTITYMETRICVALUE_INSERT = "INSERT OR IGNORE INTO entityMetricValue VALUES("
+ "(SELECT id FROM entity WHERE name = ?), (SELECT id FROM metric WHERE name = ?), ?);";
private static final String ENTITYINSTANCEMETRICVALUE_INSERT = "INSERT OR IGNORE INTO entityInstanceMetricValue VALUES("
+ "(SELECT id FROM entity WHERE name = ?), ?, (SELECT id FROM metric WHERE name = ?), ?);";
private static final String PROPERTY_INSERT = "INSERT OR IGNORE INTO property(name, type) VALUES(?, ?);";
private static final String PROPERTYVALUE_INSERT = "INSERT OR IGNORE INTO propertyValue VALUES("
+ "(SELECT id FROM entity WHERE name = ?), (SELECT id FROM property WHERE name = ?), ?, ?);";
private static final String ENTITYIDREFPROPERTYVALUE_INSERT = "INSERT OR IGNORE INTO propertyValue VALUES("
+ "(SELECT id FROM entity WHERE name = ?), (SELECT id FROM property WHERE name = ?), ?, (SELECT id FROM entity WHERE name = ?));";
private static final String EVENTIDREFPROPERTYVALUE_NO_SOURCE_INSERT = "INSERT OR IGNORE INTO propertyValue VALUES(\n"
+ "(SELECT id FROM entity WHERE name = ?),\n"
+ "(SELECT id FROM property WHERE name = ?),\n"
+ "0,\n"
+ "(IFNULL((SELECT id FROM event WHERE eventTypeId = (SELECT id FROM eventType WHERE name = ?) AND\n"
+ " entityId = (SELECT id FROM entity WHERE name = ?)), (SELECT id FROM event WHERE name = ?))));";
private static final String EVENTIDREFPROPERTYVALUE_WITH_SOURCE_INSERT = "INSERT OR IGNORE INTO propertyValue VALUES(\n"
+ "(SELECT id FROM entity WHERE name = ?),\n"
+ "(SELECT id FROM property WHERE name = ?),\n"
+ "0,\n"
+ "(IFNULL((SELECT id FROM event WHERE eventTypeId = (SELECT id FROM eventType WHERE name = ?) AND\n"
+ " entityId = (SELECT id FROM entity WHERE name = ?) AND\n"
+ " sourceEntityId = (SELECT id FROM entity WHERE name = ?)), (SELECT id FROM event WHERE name = ?))));";
private static final String TRACEEVENT_INSERT = "INSERT OR IGNORE INTO traceEvent VALUES(?, ?, (SELECT id FROM entity WHERE name = ?), ?, "
+ "(SELECT id FROM entity WHERE name = ?), ?, (SELECT id FROM eventType WHERE name = ?), ?);";
private static final String ENTITYINSTANCEMETRICVALUES_INSERT = "INSERT OR IGNORE INTO entityInstanceMetricValue SELECT\n"
+ " entityId,\n"
+ " entityInstance,\n"
+ " (SELECT id FROM metric WHERE name = ?),\n"
+ " metricValue FROM (SELECT\n"
+ " entityId,\n"
+ " entityInstance,\n"
+ " IFNULL(SUM(CASE\n"
+ " WHEN eventTypeId IN (SELECT id FROM eventType WHERE name IN (%1$s)) THEN -timestamp\n"
+ " WHEN eventTypeId IN (SELECT id FROM eventType WHERE name IN (%2$s)) THEN timestamp\n"
+ " END), 0) metricValue\n"
+ " FROM %3$sInstanceRuntimeTraceEvent GROUP BY entityId, entityInstance\n"
+ " HAVING (SELECT isComplete FROM %3$sInstanceTraceInfo WHERE\n"
+ " entityId = %3$sInstanceRuntimeTraceEvent.entityId AND\n"
+ " entityInstance = %3$sInstanceRuntimeTraceEvent.entityInstance)\n"
+ " );";
private static final String COMBINEDENTITYINSTANCEMETRICVALUES_INSERT = "INSERT OR IGNORE INTO entityInstanceMetricValue SELECT\n"
+ " entityId,\n"
+ " entityInstance,\n"
+ " (SELECT id FROM metric WHERE name = ?),\n"
+ " SUM(value)\n"
+ "FROM entityInstanceMetricValue WHERE\n"
+ " metricId IN (SELECT id FROM metric WHERE name IN (%1$s)) AND\n"
+ " (SELECT isComplete\n"
+ " FROM %2$sInstanceTraceInfo\n"
+ " WHERE entityId = entityInstanceMetricValue.entityId AND\n"
+ " entityInstance = entityInstanceMetricValue.entityInstance\n"
+ " ) = 1\n"
+ "GROUP BY entityId, entityInstance;";
private static final String INTERENTITYINSTANCEMETRICVALUES_INSERT = "INSERT OR IGNORE INTO entityInstanceMetricValue SELECT\n"
+ " entityId,\n"
+ " entityInstance,\n"
+ " (SELECT id FROM metric WHERE name = ?),\n"
+ " metricValue FROM (SELECT\n"
+ " A.entityId,\n"
+ " A.entityInstance,\n"
+ " SUM(B.timestamp - A.timestamp) AS metricValue\n"
+ " FROM (SELECT * FROM %1$sInstanceRuntimeTraceEvent) AS A INNER JOIN %1$sInstanceRuntimeTraceEvent AS B ON\n"
+ " B.entityId = A.entityId AND B.entityInstance = A.entityInstance + 1\n"
+ " WHERE A.eventTypeId = (SELECT id FROM eventType WHERE name = ?) AND\n"
+ " B.eventTypeId = (SELECT id FROM eventType WHERE name = ?)\n"
+ " GROUP BY A.entityId, A.entityInstance HAVING\n"
+ " (SELECT isComplete FROM %1$sInstanceTraceInfo WHERE\n"
+ " entityId = A.entityId AND\n"
+ " entityInstance = A.entityInstance) AND\n"
+ " (SELECT isComplete FROM %1$sInstanceTraceInfo WHERE\n"
+ " entityId = B.entityId AND\n"
+ " entityInstance = B.entityInstance)\n"
+ " );";
private static final String INTERSOURCEENTITYINSTANCEMETRICVALUES_INSERT = "INSERT OR IGNORE INTO entityInstanceMetricValue SELECT\n"
+ " sourceEntityId,\n"
+ " sourceEntityInstance,\n"
+ " (SELECT id FROM metric WHERE name = ?),\n"
+ " metricValue FROM (SELECT\n"
+ " A.sourceEntityId,\n"
+ " A.sourceEntityInstance,\n"
+ " SUM(B.timestamp - A.timestamp) AS metricValue\n"
+ " FROM (SELECT * FROM %1$sInstanceRuntimeTraceEvent) AS A INNER JOIN %1$sInstanceRuntimeTraceEvent AS B ON\n"
+ " B.entityId = A.entityId AND B.entityInstance = A.entityInstance + 1\n"
+ " WHERE A.eventTypeId = (SELECT id FROM eventType WHERE name = ?) AND\n"
+ " B.eventTypeId = (SELECT id FROM eventType WHERE name = ?) AND\n"
+ " A.sourceEntityId = B.sourceEntityId\n"
+ " GROUP BY A.sourceEntityId, A.sourceEntityInstance HAVING\n"
+ " (SELECT isComplete FROM %1$sInstanceTraceInfo WHERE\n"
+ " entityId = A.entityId AND\n"
+ " entityInstance = A.entityInstance) AND\n"
+ " (SELECT isComplete FROM %1$sInstanceTraceInfo WHERE\n"
+ " entityId = B.entityId AND\n"
+ " entityInstance = B.entityInstance)\n"
+ " );";
private static final String AGGREGATEDMETRICS_INSERT = "INSERT OR IGNORE INTO metric(name, dimension) SELECT name || '_' || ?, dimension FROM "
+ "metric WHERE dimension = ? AND EXISTS(SELECT * FROM entityInstanceMetricValue WHERE metricId = metric.id LIMIT 1);";
private static final String AGGREGATEDMETRICVALUE_INSERT = "INSERT OR IGNORE INTO entityMetricValue SELECT entityId, (SELECT id FROM metric "
+ "WHERE name = (SELECT name FROM metric WHERE id = metricId) || '_' || ?), %1$s FROM entityInstanceMetricValue WHERE metricId IN "
+ "(SELECT id FROM metric WHERE dimension = ?) GROUP BY entityId, metricId;";
private static final String EVENTCOUNTMETRICVALUES_INSERT = "INSERT OR IGNORE INTO entityMetricValue SELECT\n"
+ " entityId,\n"
+ " (SELECT id FROM metric WHERE name = ?) AS metricId,\n"
+ " SUM(%1$sEventCount) AS value\n"
+ "FROM %2$sInstanceTraceInfo GROUP BY entityId;";
public ATDBConnection(final String dbFile) throws SQLException {
this(dbFile, AccessMode.ReadOnly);
}
public ATDBConnection(final String dbFile, final AccessMode accessMode) throws SQLException {
super(dbFile, accessMode);
}
private String getFirstStringFromPreparedQuery(final String query, final List<String> parameters, final String defaultValue) throws SQLException {
return getStringStreamFromPreparedQuery(query, parameters).findFirst().orElse(defaultValue);
}
private <T> Stream<T> getStreamFromPreparedQuery(final String query, final List<String> parameters,
final ThrowingFunction<ResultSet, T, SQLException> rowMapper) throws SQLException {
final PreparedStatement prepStmt = super.getPrepareQueryFor(query);
for(int i = 0; i < parameters.size(); i++) {
prepStmt.setString(i + 1, parameters.get(i));
}
return super.queryAndMapToStream(prepStmt, rowMapper).filter(Objects::nonNull);
}
private Stream<String> getStringStreamFromPreparedQuery(final String query, final List<String> parameters) throws SQLException {
return getStreamFromPreparedQuery(query, parameters, rs -> rs.getString(1));
}
private List<String> getStringListFromPreparedQuery(final String query, final List<String> parameters) throws SQLException {
return getStringStreamFromPreparedQuery(query, parameters).collect(Collectors.toList());
}
private Stream<Long> getLongStreamFromPreparedQuery(final String query, final List<String> parameters) throws SQLException {
return getStreamFromPreparedQuery(query, parameters, rs -> rs.getLong(1));
}
private List<Long> getLongListFromPreparedQuery(final String query, final List<String> parameters) throws SQLException {
return getLongStreamFromPreparedQuery(query, parameters).collect(Collectors.toList());
}
private String getMetaInfo(final String metaInfoKey, final String defaultValue) throws SQLException {
return getFirstStringFromPreparedQuery(METAINFORMATION_QUERY, Arrays.asList(metaInfoKey), defaultValue);
}
/**
* Returns the time base of this ATDB.
*
* @return The time base unit. If not set, "?" will be returned.
* @throws SQLException
*/
public String getTimeBase() throws SQLException {
return getMetaInfo(MetaInformation.TIME_BASE.camelName, "?");
}
/**
* Returns all entities of the specified entity type from this ATDB.
* @param entityTypeName The name of the entity type.
* @return A list of all entities of that specific type.
* @throws SQLException
*/
public List<String> getAllEntitiesByType(final String entityTypeName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_BY_TYPE_QUERY, Arrays.asList(entityTypeName));
}
/**
* Returns all instance numbers of the specified entity from this ATDB.
* @param entityName The name of the entity.
* @return A list of all instance numbers of that entity.
* @throws SQLException
*/
public List<Long> getAllInstancesForEntity(final String entityName) throws SQLException {
return getLongListFromPreparedQuery(ENTITY_INSTANCES_QUERY, Arrays.asList(entityName));
}
/**
* Returns all ECU names of this ATDB.
* @return A list of all ECU names.
* @throws SQLException
*/
public List<String> getAllECUs() throws SQLException {
return getAllEntitiesByType("ECU");
}
/**
* Returns all processor names of this ATDB for the given ecu name.
* @param ecuName The ECU name of which we want to retrieve all processor names.
* @return A list of all processor names for the given ECU.
* @throws SQLException
*/
public List<String> getProcessorsOfECU(final String ecuName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(ecuName, "ECU", EntityProperty.PROCESSORS.camelName));
}
/**
* Returns all processor names of this ATDB.
* @return A list of all processor names.
* @throws SQLException
*/
public List<String> getAllProcessors() throws SQLException {
return getAllEntitiesByType("Processor");
}
/**
* Returns all core names of this ATDB for the given processor name.
* @param processorName The processor name of which we want to retrieve all core names.
* @return A list of all core names for the given processor.
* @throws SQLException
*/
public List<String> getCoresOfProcessor(final String processorName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processorName, "Processor", EntityProperty.CORES.camelName));
}
/**
* Returns all core names of this ATDB.
* @return A list of all core names.
* @throws SQLException
*/
public List<String> getAllCores() throws SQLException {
return getAllEntitiesByType("C");
}
/**
* Returns the frequency in Hz for the given core name.
* @param coreName The core name of which we want to retrieve the frequency.
* @return The frequency in Hz as long. 0, if none was found.
* @throws SQLException
*/
public long getCoreFrequencyInHz(final String coreName) throws SQLException {
return Long.parseLong(getFirstStringFromPreparedQuery(ENTITY_PROPERTY_VALUE_QUERY, Arrays.asList(coreName, "C",
EntityProperty.FREQUENCY_IN_HZ.camelName), "0"));
}
/**
* Returns all process (task or ISR) names of this ATDB.
* @return A list of all process names.
* @throws SQLException
*/
public List<String> getAllProcesses() throws SQLException {
return Stream.concat(
getStringStreamFromPreparedQuery(ENTITY_BY_TYPE_QUERY, List.of("T")),
getStringStreamFromPreparedQuery(ENTITY_BY_TYPE_QUERY, List.of("I"))
).collect(Collectors.toList());
}
/**
* Returns all task names of this ATDB.
* @return A list of all task names.
* @throws SQLException
*/
public List<String> getAllTasks() throws SQLException {
return getAllEntitiesByType("T");
}
/**
* Returns all ISR (Interrupt Service Routine) names of this ATDB.
* @return A list of all ISR names.
* @throws SQLException
*/
public List<String> getAllISRs() throws SQLException {
return getAllEntitiesByType("I");
}
/**
* Returns the name of the core that executes the process specified by the process name.
* @param processName The process name of which we want to retrieve the executing core.
* @return The core name on which the process is executed. Empty, if none was found.
* @throws SQLException
*/
public String getExecutingCoreOfProcess(final String processName) throws SQLException {
final Optional<String> coreOfTask = getStringStreamFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName,
"T", EntityProperty.EXECUTING_CORE.camelName)).findFirst();
if (!coreOfTask.isPresent()) {
return getFirstStringFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName,
"I", EntityProperty.EXECUTING_CORE.camelName), "");
} else {
return coreOfTask.get();
}
}
/**
* Returns all runnable names of this ATDB that are called by the given process name.
* @param processName The process name of which we want to retrieve all runnable names.
* @return A list of all runnable names called by the given process.
* @throws SQLException
*/
public List<String> getRunnablesOfProcess(final String processName) throws SQLException {
return Stream.concat(
getStringStreamFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName, "T", EntityProperty.RUNNABLES.camelName)),
getStringStreamFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName, "I", EntityProperty.RUNNABLES.camelName))
).collect(Collectors.toList());
}
/**
* Returns all stimulus names of this ATDB that activate the given process name.
* @param processName The process name of which we want to retrieve all stimulus names.
* @return A list of all stimulus names activating the given process.
* @throws SQLException
*/
public List<String> getStimuliOfProcess(final String processName) throws SQLException {
return Stream.concat(
getStringStreamFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName, "T", EntityProperty.STIMULI.camelName)),
getStringStreamFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(processName, "I", EntityProperty.STIMULI.camelName))
).collect(Collectors.toList());
}
/**
* Returns all runnable names of this ATDB.
* @return A list of all runnable names.
* @throws SQLException
*/
public List<String> getAllRunnables() throws SQLException {
return getAllEntitiesByType("R");
}
/**
* Returns all label names of this ATDB that are read by the given runnable name.
* @param runnableName The runnable name of which we want to retrieve all read labels.
* @return A list of all label names read by the given runnable.
* @throws SQLException
*/
public List<String> getLabelsReadByRunnable(final String runnableName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(runnableName, "R", EntityProperty.READ_SIGNALS.camelName));
}
/**
* Returns all label names of this ATDB that are written by the given runnable name.
* @param runnableName The runnable name of which we want to retrieve all written labels.
* @return A list of all label names written by the given runnable.
* @throws SQLException
*/
public List<String> getLabelsWrittenByRunnable(final String runnableName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(runnableName, "R", EntityProperty.WRITTEN_SIGNALS.camelName));
}
/**
* Returns all stimulus names of this ATDB.
* @return A list of all stimulus names.
* @throws SQLException
*/
public List<String> getAllStimuli() throws SQLException {
return getAllEntitiesByType("STI");
}
/**
* Returns all label names of this ATDB.
* @return A list of all label names.
* @throws SQLException
*/
public List<String> getAllLabels() throws SQLException {
return getAllEntitiesByType("SIG");
}
/**
* Returns the initial value for the given label name.
* @param labelName The label name of which we want to retrieve the initial value.
* @return The initial value as string. Empty, if none was found.
* @throws SQLException
*/
public String getLabelInitialValue(final String labelName) throws SQLException {
return getFirstStringFromPreparedQuery(ENTITY_PROPERTY_VALUE_QUERY, Arrays.asList(labelName, "SIG", EntityProperty.INITIAL_VALUE.camelName), "");
}
/**
* Returns all event chain names of this ATDB.
* @return A list of all event chain names.
* @throws SQLException
*/
public List<String> getAllEventChains() throws SQLException {
return getAllEntitiesByType(EC);
}
/**
* Returns all event (specification, not from the actual trace!) names of this ATDB.
* @return A list of all event names.
* @throws SQLException
*/
public List<String> getAllEvents() throws SQLException {
return getStringListFromPreparedQuery(EVENTS_QUERY, Collections.emptyList());
}
/**
* Returns all event (specification, not from the actual trace!) names of this ATDB of the given event type.
* @param eventTypeName The event type name of which the returned event names shall be.
* @return A list of all event names.
* @throws SQLException
*/
public List<String> getAllEventsByType(final String eventTypeName) throws SQLException {
return getStringListFromPreparedQuery(EVENT_BY_TYPE_QUERY, Arrays.asList(eventTypeName));
}
/**
* Returns all process (task or ISR) event (specification, not from the actual trace!) names of this ATDB.
* @return A list of all process event names.
* @throws SQLException
*/
public List<String> getAllProcessEvents() throws SQLException {
return Stream.concat(
getStringStreamFromPreparedQuery(EVENT_BY_ENTITY_TYPE_QUERY, List.of("T")),
getStringStreamFromPreparedQuery(EVENT_BY_ENTITY_TYPE_QUERY, List.of("I"))
).collect(Collectors.toList());
}
/**
* Returns all runnable event (specification, not from the actual trace!) names of this ATDB.
* @return A list of all runnable event names.
* @throws SQLException
*/
public List<String> getAllRunnableEvents() throws SQLException {
return getStringListFromPreparedQuery(EVENT_BY_ENTITY_TYPE_QUERY, List.of("R"));
}
/**
* Returns all label event (specification, not from the actual trace!) names of this ATDB.
* @return A list of all label event names.
* @throws SQLException
*/
public List<String> getAllLabelEvents() throws SQLException {
return getStringListFromPreparedQuery(EVENT_BY_ENTITY_TYPE_QUERY, List.of("SIG"));
}
/**
* Returns all stimulus event (specification, not from the actual trace!) names of this ATDB.
* @return A list of all stimulus event names.
* @throws SQLException
*/
public List<String> getAllStimulusEvents() throws SQLException {
return getStringListFromPreparedQuery(EVENT_BY_ENTITY_TYPE_QUERY, List.of("STI"));
}
/**
* Returns the event type name for the given event name.
* @param eventName The name of the event of which we want to know the type.
* @return The type name. Empty, if none was found.
* @throws SQLException
*/
public String getEventTypeForEvent(final String eventName) throws SQLException {
return getFirstStringFromPreparedQuery(EVENT_TYPE_OF_EVENT_QUERY, Arrays.asList(eventName), "");
}
/**
* Returns the entity name for the given event name.
* @param eventName The name of the event of which we want to know the affected entity.
* @return The entity name. Empty, if none was found.
* @throws SQLException
*/
public String getEntityForEvent(final String eventName) throws SQLException {
return getFirstStringFromPreparedQuery(ENTITY_OF_EVENT_QUERY, Arrays.asList(eventName), "");
}
/**
* Returns the source entity name for the given event name.
* @param eventName The name of the event of which we want to know the source entity.
* @return The source entity name. Empty, if none was found.
* @throws SQLException
*/
public String getSourceEntityForEvent(final String eventName) throws SQLException {
return getFirstStringFromPreparedQuery(SOURCE_ENTITY_OF_EVENT_QUERY, Arrays.asList(eventName), "");
}
/**
* Returns the stimulus event name for the given event chain name. If there are multiple stimulus events, they will be separated by a ', '.
* @param eventChainName The name of the event chain from which we want to know the stimulus event.
* @return The stimulus event name. Empty, if none was found.
* @throws SQLException
*/
public String getEventChainStimulus(final String eventChainName) throws SQLException {
return getFirstStringFromPreparedQuery(EVENTCHAIN_EVENTREF_QUERY, Arrays.asList(EntityProperty.EC_STIMULUS.camelName, eventChainName), "");
}
/**
* Returns the response event name for the given event chain name. If there are multiple response events, they will be separated by a ', '.
* @param eventChainName The name of the event chain from which we want to know the response event.
* @return The response event name. Empty, if none was found.
* @throws SQLException
*/
public String getEventChainResponse(final String eventChainName) throws SQLException {
return getFirstStringFromPreparedQuery(EVENTCHAIN_EVENTREF_QUERY, Arrays.asList(EntityProperty.EC_RESPONSE.camelName, eventChainName), "");
}
/**
* Returns the names of the item event chains for the given event chain name.
* @param eventChainName The name of the event chain from which we want to know the item event chain names.
* @return The item event chain names.
* @throws SQLException
*/
public List<String> getEventChainItems(final String eventChainName) throws SQLException {
return getStringListFromPreparedQuery(ENTITY_PROPERTY_ENTITYREF_QUERY, Arrays.asList(eventChainName, EC, EntityProperty.EC_ITEMS.camelName));
}
/**
* Returns the minimum items complete value for the given event chain. If it is not set, the default value of 0 is returned;
* @param eventChainName The name of the event chain from which we want to know the minimum items complete value.
* @return The minimum number of complete items.
* @throws SQLException
*/
public int getEventChainMinItemsCompleted(final String eventChainName) throws SQLException {
return Integer.parseInt(getFirstStringFromPreparedQuery(ENTITY_PROPERTY_VALUE_QUERY, Arrays.asList(eventChainName, EC,
EntityProperty.EC_MIN_ITEMS_COMPLETED.camelName), "0"));
}
/**
* Returns all metric names contained in this ATDB, some of which are specific to certain entity types.
* @return All metric names.
* @throws SQLException
*/
public List<String> getAllMetrics() throws SQLException {
return getStringListFromPreparedQuery(METRICS_QUERY, Collections.emptyList());
}
/**
* Returns the value of the metric for the given entity and metric names.
* @param entityName The name of the entity from which we want to know the metric value.
* @param metricName The name of the metric from which we want to know the value for the specified entity.
* @return The value for the metric and entity. Empty, if none is found.
* @throws SQLException
*/
public String getValueForMetricAndEntity(final String entityName, final String metricName) throws SQLException {
return getFirstStringFromPreparedQuery(METRICVALUE_QUERY, Arrays.asList(entityName, metricName), "");
}
/**
* Inserts a new entry of arbitrary meta information into the ATDB.
* @param infoName Meta information name/key.
* @param infoValue Meta information value.
* @throws SQLException
*/
public void insertMetaInformation(final String infoName, final String infoValue) throws SQLException {
executeBatchablePrepStmt(METAINFORMATION_INSERT, Arrays.asList(infoName, infoValue));
}
/**
* Insert the meta information for the time base of the ATDB.
* @param newTimeBase The time base of the ATDB (e.g. "us", or "ms").
* @throws SQLException
*/
public void setTimeBase(final String newTimeBase) throws SQLException {
insertMetaInformation(MetaInformation.TIME_BASE.camelName, newTimeBase);
}
/**
* Inserts a new entity type with the given name into the ATDB.
* @param name Name of the entity type.
* @throws SQLException
*/
public void insertEntityType(final String name) throws SQLException {
executeBatchablePrepStmt(ENTITYTYPE_INSERT, Arrays.asList(name));
}
/**
* Immediately inserts a new entity type with the given name into the ATDB and returns the newly generated id for it.
* @param name Name of the entity type.
* @return The generated id of the inserted entity type.
* @throws SQLException
*/
public long immediateInsertEntityType(final String name) throws SQLException {
return executePrepStmtAndGetGeneratedId(ENTITYTYPE_INSERT, Arrays.asList(name));
}
/**
* Inserts a new entity with the given name and entity type into the ATDB.
* @param name The name of the entity.
* @param entityTypeName The name of the entity's type.
* @throws SQLException
*/
public void insertEntity(final String name, final String entityTypeName) throws SQLException {
executeBatchablePrepStmt(ENTITY_INSERT, Arrays.asList(name, entityTypeName));
}
/**
* Immediately inserts a new entity with the given name and entity type id into the ATDB and returns the newly generated id for it.
* @param name The name of the entity.
* @param entityTypeId The id of the entity's type.
* @return The generated id of the inserted entity.
* @throws SQLException
*/
public long immediateInsertEntity(final String name, final long entityTypeId) throws SQLException {
return executePrepStmtAndGetGeneratedId(ENTITY_INSERT_WITH_TYPE_ID, Arrays.asList(name, entityTypeId == -1 ? null : entityTypeId));
}
/**
* Inserts an entity instance for the given entity name and instance number into the ATDB.
* @param entityName Name of the entity.
* @param instNumber Number of the entity instance to be inserted.
* @throws SQLException
*/
public void insertEntityInstance(final String entityName, final long instNumber) throws SQLException {
executeBatchablePrepStmt(ENTITYINSTANCE_INSERT, Arrays.asList(entityName, instNumber));
}
/**
* Inserts one or more entity instances for the given entity name into the ATDB. The instance numbers for each
* of which a new instance will be inserted are taken from the LongStrem.
* @param entityName Name of the entity.
* @param instNumbers LongStream containing all instance numbers to be inserted.
* @throws SQLException
*/
public void insertEntityInstances(final String entityName, final LongStream instNumbers) throws SQLException {
final OfLong numberIter = instNumbers.iterator();
while (numberIter.hasNext()) {
insertEntityInstance(entityName,numberIter.nextLong());
}
}
/**
* Inserts a new event type for the given name into the ATDB.
* @param name The name of the event type to insert.
* @throws SQLException
*/
public void insertEventType(final String name) throws SQLException {
executeBatchablePrepStmt(EVENTTYPE_INSERT, Arrays.asList(name));
}
/**
* Immediately inserts a new event type for the given name into the ATDB and returns the newly generated id for it.
* @param name The name of the event type to insert.
* @return The generated id of the inserted event type.
* @throws SQLException
*/
public long immediateInsertEventType(final String name) throws SQLException {
return executePrepStmtAndGetGeneratedId(EVENTTYPE_INSERT, Arrays.asList(name));
}
/**
* Inserts an event for the given name and event type name into the ATDB. The entity that shall be subject to the event is given by name
* as well as the optional source entity.
* @param name Name of the event to insert.
* @param eventTypeName Name of the type of event.
* @param entityName Name of the entity that shall be subject to this event.
* @param sourceEntityName Optional source entity name. Empty String or null is ok.
* @throws SQLException
*/
public void insertEvent(final String name, final String eventTypeName, final String entityName, final String sourceEntityName)
throws SQLException {
executeBatchablePrepStmt(EVENT_INSERT, Arrays.asList(name, eventTypeName, entityName, sourceEntityName));
}
/**
* Inserts a metric for the given name and dimension into the ATDB.
* @param name The name of the new metric.
* @param dimension The dimension, e.g. time.
* @throws SQLException
*/
public void insertMetric(final String name, final String dimension) throws SQLException {
executeBatchablePrepStmt(METRIC_INSERT, Arrays.asList(name, dimension));
}
/**
* Inserts a new value entry for the given entity and metric name into the ATDB.
* @param entityName Name of the entity for the metric value.
* @param metricName Name of the metric for the new value.
* @param value The value of the metric.
* @throws SQLException
*/
public void insertEntityMetricValue(final String entityName, final String metricName, final Object value) throws SQLException {
executeBatchablePrepStmt(ENTITYMETRICVALUE_INSERT, Arrays.asList(entityName, metricName, value));
}
/**
* Inserts a new value entry for the given entity instance and metric name into the ATDB.
* @param entityName Name of the entity for the metric value.
* @param entityInstNumber Instance number to uniquely identify the entity instance.
* @param metricName Name of the metric for the new value.
* @param value The value of the metric.
* @throws SQLException
*/
public void insertEntityInstanceMetricValue(final String entityName, final int entityInstNumber, final String metricName,
final Object value) throws SQLException {
executeBatchablePrepStmt(ENTITYINSTANCEMETRICVALUE_INSERT, Arrays.asList(entityName, entityInstNumber, metricName, value));
}
/**
* Inserts a new property with the given name and property type into the ATDB.
* @param name The name of the new property.
* @param propertyType The type, e.g. entityIdRef, long, time, ...
* @throws SQLException
*/
public void insertProperty(final String name, final String propertyType) throws SQLException {
executeBatchablePrepStmt(PROPERTY_INSERT, Arrays.asList(name, propertyType));
}
/**
* Inserts a property value for the given entity and property into the ATDB. Multiple values can be provided as a
* collection in the value object.
* @param entityName The name of the entity that has the property.
* @param propertyName The name of the property for which the value shall be set.
* @param value The value of the property (use a collection to provide multiple values).
* @throws SQLException
*/
public void insertPropertyValue(final String entityName, final String propertyName, final Object value) throws SQLException {
if (value instanceof Collection<?>) {
int sqcnr = 0;
for(Object collectionElement:(Collection<?>)value) {
executeBatchablePrepStmt(PROPERTYVALUE_INSERT, Arrays.asList(entityName, propertyName, sqcnr, collectionElement));
sqcnr++;
}
} else {
executeBatchablePrepStmt(PROPERTYVALUE_INSERT, Arrays.asList(entityName, propertyName, 0, value));
}
}
/**
* Convenience method to insert a single valued entity id reference property for the given entity into the ATDB. This call is
* forwarded to {@link #insertEntityRefsPropertyValue(String, String, List)} with a singleton list as referredEntityNames.
* @param entityName The name of the entity that has the property.
* @param propertyName The name of the property for which the value shall be set. The type of that property is expected to be "entityIdRef".
* @param referredEntityName The name of the entity whose id shall be set as the value.
* @throws SQLException
*/
public void insertEntityRefPropertyValue(final String entityName, final String propertyName, final String referredEntityName)
throws SQLException {
this.insertEntityRefsPropertyValue(entityName, propertyName, Collections.singletonList(referredEntityName));
}
/**
* Inserts a property value for the given entity and property into the ATDB. Multiple referred entity names can be passed to set multiple
* entity id references as value.
* @param entityName The name of the entity that has the property.
* @param propertyName The name of the property for which the value shall be set. The type of that property is expected to be "entityIdRef".
* @param referredEntityNames The names of the entities whose ids shall be set as the values.
* @throws SQLException
*/
public void insertEntityRefsPropertyValue(final String entityName, final String propertyName, final List<String> referredEntityNames)
throws SQLException {
if (referredEntityNames.isEmpty()) return;
if (referredEntityNames.size() > 1) {
int sqcnr = 0;
for(final String referredEntityName:referredEntityNames) {
executeBatchablePrepStmt(ENTITYIDREFPROPERTYVALUE_INSERT, Arrays.asList(entityName, propertyName, sqcnr, referredEntityName));
sqcnr++;
}
} else {
executeBatchablePrepStmt(ENTITYIDREFPROPERTYVALUE_INSERT, Arrays.asList(entityName, propertyName, 0, referredEntityNames.get(0)));
}
}
/**
* Inserts a property value for the given entity and property into the ATDB. The single value is an event id which will be queried with the
* provided information: eventName (can be empty if unknown), eventTypeName (can be empty if eventName is known), subjectEntityName (can be
* empty if eventName is known), sourceEntityName (can be empty).
* @param entityName The name of the entity that has the property.
* @param propertyName The name of the property for which the value shall be set. The type of that property is expected to be "eventIdRef".
* @param eventName The name of the event that shall be referred to.
* @param eventTypeName The type of the event that shall be referred to.
* @param subjectEntityName The name of the subject entity of the event that shall be referred to.
* @param sourceEntityName The name of the source entity of the event that shall be referred to.
* @throws SQLException
*/
public void insertEventRefPropertyValue(final String entityName, final String propertyName, final String eventName,
final String eventTypeName, final String subjectEntityName, final String sourceEntityName) throws SQLException {
if (sourceEntityName.length() == 0) {
executeBatchablePrepStmt(EVENTIDREFPROPERTYVALUE_NO_SOURCE_INSERT, Arrays.asList(entityName, propertyName, eventTypeName,
subjectEntityName, eventName));
} else {
executeBatchablePrepStmt(EVENTIDREFPROPERTYVALUE_WITH_SOURCE_INSERT, Arrays.asList(entityName, propertyName, eventTypeName,
subjectEntityName, sourceEntityName, eventName));
}
}
/**
* Inserts a new trace event into the ATDB.
* @param timestamp Time stamp of the new event.
* @param sqcnr Counting number, in case there are multiple events at the same time stamp.
* @param entityName Name of the entity that is subject to the event.
* @param entityInstNumber Instance number of the subject entity.
* @param sourceEntityName Name of the entity that is the source of the event.
* @param sourceEntityInstNumber Instance number of the source entity.
* @param eventTypeName Name of the type of event.
* @param value Optional value set/associated with the event. Null can be passed.
* @throws SQLException
*/
public void insertTraceEvent(final long timestamp, final int sqcnr, final String entityName, final int entityInstNumber,
final String sourceEntityName, final int sourceEntityInstNumber, final String eventTypeName, final Object value)
throws SQLException {
// parameters may be null
executeBatchablePrepStmt(TRACEEVENT_INSERT, Arrays.asList(timestamp, sqcnr, entityName, entityInstNumber,
sourceEntityName, sourceEntityInstNumber, eventTypeName, value));
}
/**
* Inserts a new metric for the given name with dimension 'time'. Then inserts multiple values for all entity instances of type
* <code>entityType</code> which are complete and have the provided events. The values inserted are the times between the entering and
* leaving events. For example: The runtime of a runnable is the time passed between the 'start' and 'terminate' time. The call for this
* example is as follows: <code>insertEntityInstanceStateMetricValuesForEntityType("running", EntityType.runnable, ["start"], ["terminate"])</code>.
* @param metricName The name of the time metric to be inserted.
* @param entityType The name of the entity type for which the metric shall be calculated.
* @param stateEnteringEvents The events that mark the start times.
* @param stateleavingEvents The events that mark the end times.
* @throws SQLException
*/
public void insertEntityInstanceStateMetricValuesForEntityType(final String metricName, final EntityType<?> entityType,
final Collection<String> stateEnteringEvents, final Collection<String> stateleavingEvents) throws SQLException {
insertMetric(metricName, "time");
// map and collect state entering events as SQL list
final String enteringEvents = stateEnteringEvents.stream().map(e -> "'" + e.toLowerCase() + "'").collect(Collectors.joining(", "));
// map and collect state leaving events as SQL list
final String leavingEvents = stateleavingEvents.stream().map(e -> "'" + e.toLowerCase() + "'").collect(Collectors.joining(", "));
executeBatchablePrepStmt(String.format(ENTITYINSTANCEMETRICVALUES_INSERT, enteringEvents, leavingEvents, entityType.getName()),
Arrays.asList(metricName));
}
/**
* Inserts a new metric for the given name with dimension 'time'. Then inserts multiple values for all entity instances of type
* <code>entityType</code> which are complete and have entries for the provided list of metrics. The values of the provided metrics to
* combine will be summed and inserted as new entry for the metric.
* @param metricName The name of the time metric to be inserted.
* @param entityType The name of the entity type for which the metric shall be calculated.
* @param metricNamesToCombine A list of all the metrics whose values shall be summed and inserted for this new metric.
* @throws SQLException
*/
public void insertCombinedEntityInstanceStateMetricValuesForEntityType(final String metricName, final EntityType<?> entityType,
final List<String> metricNamesToCombine) throws SQLException {
insertMetric(metricName, "time");
final String cStates = metricNamesToCombine.stream().map(s -> "'" + s + "'").collect(Collectors.joining(", "));
executeBatchablePrepStmt(String.format(COMBINEDENTITYINSTANCEMETRICVALUES_INSERT, cStates, entityType.getName()), Arrays.asList(metricName));
}
/**
* Inserts a new metric for the given name with dimension 'time'. Then inserts multiple values for all neighboring pairs of
* entity instances of type <code>entityType</code> which are complete and have the two provided events. For example: The start-to-start
* time of a runnable is the time between 'start' events from two consecutive runnable instances. The call for this example is as follows:
* <code>insertInterEntityInstanceMetricValuesForEntityType("startToStart", EntityType.runnable, "start", "start")</code>. You can also
* provide differing events like "terminate" and "start" to determine the end-to-start times.
* @param metricName The name of the time metric to be inserted.
* @param entityType The name of the entity type for which the metric shall be calculated.
* @param firstInstanceEvent The event of the first instance to be considered.
* @param secondInstanceEvent The event of the second instance to be considered.
* @throws SQLException
*/
public void insertInterEntityInstanceMetricValuesForEntityType(final String metricName, final EntityType<?> entityType,
final String firstInstanceEvent, final String secondInstanceEvent) throws SQLException {
insertMetric(metricName, "time");
executeBatchablePrepStmt(String.format(INTERENTITYINSTANCEMETRICVALUES_INSERT, entityType.getName()), Arrays.asList(metricName,
firstInstanceEvent, secondInstanceEvent));
}
/**
* Inserts a new metric for the given name with dimension 'time'. Then inserts multiple values for all neighboring pairs of
* entity instances of type <code>entityType</code> which are complete and have the provided event. The metric will be inserted
* for the source entity instance. This is useful to e.g. capture differences between activation times of a task for a stimulus entity.
* @param metricName The name of the time metric to be inserted.
* @param entityType The name of the entity type for which the metric shall be calculated.
* @param entityInstanceEvent The name of the event to be considered for both source entity instances.
* @throws SQLException
*/
public void insertInterSourceEntityInstanceMetricValuesForEntityType(final String metricName, final EntityType<?> entityType,
final String entityInstanceEvent) throws SQLException {
insertMetric(metricName, "time");
executeBatchablePrepStmt(String.format(INTERSOURCEENTITYINSTANCEMETRICVALUES_INSERT, entityType.getName()), Arrays.asList(metricName,
entityInstanceEvent, entityInstanceEvent));
}
/**
* Inserts aggregated metrics based on existing metrics with the given dimension. These metrics are only calculated if they have entries
* in the entity instance metric value table. There will be an aggregated metric for each literal in {@link MetricAggregation} with the
* name schema: {metricName}_{MetricAggregation literal}.
* @param dimension The dimension by which all metrics shall be filtered to be aggregated, e.g. 'time'.
* @throws SQLException
*/
public void insertAggregatedEntityInstanceMetricsForDimension(final String dimension) throws SQLException {
for(final MetricAggregation ma:MetricAggregation.values()) {
executeBatchablePrepStmt(AGGREGATEDMETRICS_INSERT, Arrays.asList(ma.name(), dimension));
executeBatchablePrepStmt(String.format(AGGREGATEDMETRICVALUE_INSERT, ma.getSQLStr("value")), Arrays.asList(ma.name(), dimension));
}
}
/**
* Inserts a new metric for the given name with dimension 'count'. Then inserts multiple values for all entity instances of type
* <code>entityType</code> and trace events of type <code>eventType</code>. This can be used to e.g. count the number of preemptions
* per task instance.
* @param metricName The name of the count metric to be inserted.
* @param entityType The name of the entity type for which the metric shall be calculated.
* @param eventType The name of the event type that shall be counted.
* @throws SQLException
*/
public void insertCountsForEntityTypeAndEvent(final String metricName, final EntityType<?> entityType,
final String eventType) throws SQLException {
insertMetric(metricName, "count");
executeBatchablePrepStmt(String.format(EVENTCOUNTMETRICVALUES_INSERT, eventType, entityType.getName()), Arrays.asList(metricName));
}
/**
* Inserts a new event chain entity for the given name into the ATDB.
* @param name The name of the event chain to be inserted.
* @throws SQLException
*/
public void insertEventChain(final String name) throws SQLException {
insertEntityType(EC);
insertEntity(name, EC);
}
/**
* Inserts a new event chain entity for the given name into the ATDB. The stimulus and response property values will be set for the
* corresponding event names passed.
* @param name The name of the event chain to be inserted.
* @param stimulusEventName The name of the stimulus event that shall be set for the new event chain.
* @param responseEventName The name of the response event that shall be set for the new event chain.
* @throws SQLException
*/
public void insertEventChain(final String name, final String stimulusEventName, final String responseEventName) throws SQLException {
insertEventChain(name);
insertEventRefPropertyValue(name, EntityProperty.EC_STIMULUS.camelName, stimulusEventName, "", "", "");
insertEventRefPropertyValue(name, EntityProperty.EC_RESPONSE.camelName, responseEventName, "", "", "");
}
}