package io.vivarium.persistence; import java.sql.Array; import java.sql.Connection; import java.sql.SQLException; import java.sql.Timestamp; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import com.google.common.base.Preconditions; import io.vivarium.db.DatabaseUtils; import io.vivarium.db.Relation; import io.vivarium.util.UUID; import io.vivarium.util.Version; import lombok.EqualsAndHashCode; import lombok.ToString; @EqualsAndHashCode(callSuper = true) @ToString public class WorkerModel extends PersistenceModel { // Table name private static final String TABLE_NAME = "workers"; // Column names private static final String ID = "id"; private static final String THROUGHPUTS = "throughputs"; private static final String IS_ACTIVE = "is_active"; private static final String LAST_ACTIVITY = "last_activity"; private static final String CODE_VERSION = "code_version"; private static final String FILE_FORMAT_VERSION = "file_format_version"; // relation data private final UUID workerID; private final long[] throughputs; private final boolean isActive; private final Timestamp lastActivity; private final int fileFormatVersion; private final Version codeVersion; // insert into workers (id, throughputs, is_active, last_activity, file_format_version, code_version) select // 'ec1bb1e7-d471-363e-7724-bf995021f543', '{100, 150, 200}', true, now(), 1, '{0,3,2}'; public WorkerModel(UUID workerID, long[] throughputs, boolean isActive, Timestamp lastActivity, int fileFormatVersion, Version codeVersion) { Preconditions.checkNotNull(workerID, "workerID cannot be null"); Preconditions.checkNotNull(throughputs, "throughputs cannot be null"); Preconditions.checkNotNull(lastActivity, "lastActivity cannot be null"); Preconditions.checkNotNull(codeVersion, "codeVersion cannot be null"); this.workerID = workerID; this.throughputs = throughputs; this.isActive = isActive; this.lastActivity = lastActivity; this.fileFormatVersion = fileFormatVersion; this.codeVersion = codeVersion; } static List<WorkerModel> getFromDatabase(Connection connection) throws SQLException { List<WorkerModel> results = new LinkedList<>(); List<Map<String, Object>> relations = DatabaseUtils.select(connection, TABLE_NAME, Optional.empty()); for (Map<String, Object> relationMap : relations) { results.add(inflateFromMap(relationMap)); } return results; } static Optional<WorkerModel> getFromDatabase(Connection connection, UUID resourceID) throws SQLException { List<Map<String, Object>> relations = DatabaseUtils.select(connection, TABLE_NAME, Optional.of(Relation.equalTo(ID, resourceID))); if (relations.size() == 1) { Map<String, Object> relationMap = relations.get(0); return Optional.of(inflateFromMap(relationMap)); } else if (relations.isEmpty()) { return Optional.empty(); } else { throw new IllegalStateException("Select of Resource returned multiple objects"); } } private static WorkerModel inflateFromMap(Map<String, Object> map) throws SQLException { UUID id = UUID.fromString(map.get(ID).toString()); long[] throughputs = (long[]) DatabaseUtils.toPrimitiveArray((Array) map.get(THROUGHPUTS), long.class); boolean isActive = (Boolean) map.get(IS_ACTIVE); Timestamp lastActivity = (Timestamp) map.get(LAST_ACTIVITY); int fileFormatVersion = (Integer) map.get(FILE_FORMAT_VERSION); int[] versionComponents = (int[]) DatabaseUtils.toPrimitiveArray((Array) map.get(CODE_VERSION), int.class); Version codeVersion = new Version(versionComponents); WorkerModel model = new WorkerModel(id, throughputs, isActive, lastActivity, fileFormatVersion, codeVersion); return model; } @Override protected void persistToDatabase(Connection connection) throws SQLException { Map<String, Object> resourceRelation = new HashMap<>(); resourceRelation.put(ID, workerID); resourceRelation.put(THROUGHPUTS, throughputs); resourceRelation.put(IS_ACTIVE, isActive); resourceRelation.put(LAST_ACTIVITY, lastActivity); resourceRelation.put(CODE_VERSION, codeVersion); resourceRelation.put(FILE_FORMAT_VERSION, fileFormatVersion); DatabaseUtils.upsert(connection, TABLE_NAME, resourceRelation, getPrimaryKeys()); connection.commit(); } private List<String> getPrimaryKeys() { List<String> primaryKeys = new LinkedList<>(); primaryKeys.add(ID); return primaryKeys; } public UUID getWorkerID() { return workerID; } public long[] getThroughputs() { return throughputs; } public boolean isActive() { return isActive; } public Timestamp getLastActivity() { return lastActivity; } public int getFileFormatVersion() { return fileFormatVersion; } public Version getCodeVersion() { return codeVersion; } }