listUsers() {
try (var sql = new AllUsersSQL()) {
- return sql.transactionRead(() -> sql.allUsers());
+ return sql.transactionRead(sql::allUsers);
}
}
@@ -596,24 +597,6 @@ public PasswordChangeRecord updateUser(Principal principal,
}
}
- /**
- * Just a tuple extracted from a row. Only used in
- * {@link #updateUser(Principal,PasswordChangeRecord,UpdatePassSQL)}; it's
- * only not a local class to work around JDK-8144673 (fixed
- * by Java 11).
- */
- private static class GetUserResult {
- final PasswordChangeRecord baseUser;
-
- final String oldEncPass;
-
- GetUserResult(Row row) {
- baseUser = passChange(row);
- oldEncPass = row.getString("encrypted_password");
- }
- }
-
/**
* Back end of {@link #updateUser(Principal,PasswordChangeRecord)}.
*
@@ -626,10 +609,28 @@ private static class GetUserResult {
* What to update
* @param sql
* How to touch the DB
- * @return What was updated
+ * @return What was updated, without the actual password fields
+ * filled out.
*/
private PasswordChangeRecord updateUser(Principal principal,
PasswordChangeRecord user, UpdatePassSQL sql) {
+ /**
+ * Record extracted from a row of the {@code user_info} table.
+ *
+ * @param baseUser
+ * The user's password change record, without the
+ * actual password fields filled out.
+ * @param oldEncPass
+ * Old encoded password.
+ * @see UserControl#updateUser(Principal, PasswordChangeRecord,
+ * UpdatePassSQL)
+ */
+ record GetUserResult(PasswordChangeRecord baseUser, String oldEncPass) {
+ private GetUserResult(Row row) {
+ this(passChange(row), row.getString("encrypted_password"));
+ }
+ }
+
var result = sql
.transaction(() -> sql.getPasswordedUser
.call1(GetUserResult::new, principal.getName()))
@@ -641,7 +642,7 @@ private PasswordChangeRecord updateUser(Principal principal,
// This is a SLOW operation; must not hold transaction here
if (!passServices.matchPassword(user.getOldPassword(),
- result.oldEncPass)) {
+ result.oldEncPass())) {
throw new BadCredentialsException("bad password");
}
@@ -652,11 +653,11 @@ private PasswordChangeRecord updateUser(Principal principal,
var newEncPass = passServices.encodePassword(user.getNewPassword());
return sql.transaction(() -> {
if (sql.setPassword.call(newEncPass,
- result.baseUser.getUserId()) != 1) {
+ result.baseUser().getUserId()) != 1) {
throw new InternalAuthenticationServiceException(
"failed to update database");
}
- return result.baseUser;
+ return result.baseUser();
});
}
@@ -667,7 +668,7 @@ private PasswordChangeRecord updateUser(Principal principal,
*/
public List listGroups() {
try (var sql = new GroupsSQL()) {
- return sql.transactionRead(() -> sql.listGroups());
+ return sql.transactionRead(sql::listGroups);
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTask.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTask.java
index 416907d280..ca9234488b 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTask.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTask.java
@@ -44,7 +44,7 @@
import java.util.Set;
import java.util.stream.Stream;
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -131,6 +131,13 @@ public class AllocatorTask extends DatabaseAwareBean
// instead set by setter in postconstruct of BMPController
private BMPController bmpController;
+ /**
+ * Only called by BMP controller.
+ *
+ * @param bmpController
+ * The BMP controller
+ * @hidden
+ */
public void setBMPController(BMPController bmpController) {
this.bmpController = bmpController;
}
@@ -138,10 +145,10 @@ public void setBMPController(BMPController bmpController) {
@PostConstruct
@SuppressWarnings("FutureReturnValueIgnored")
private void init() {
- scheduler.scheduleAtFixedRate(() -> allocate(), allocProps.getPeriod());
- scheduler.scheduleAtFixedRate(() -> expireJobs(),
+ scheduler.scheduleAtFixedRate(this::allocate, allocProps.getPeriod());
+ scheduler.scheduleAtFixedRate(this::expireJobs,
keepAliveProps.getExpiryPeriod());
- scheduler.schedule(() -> tombstone(),
+ scheduler.schedule(this::tombstone,
new CronTrigger(historyProps.getSchedule()));
}
@@ -215,21 +222,14 @@ private boolean update(int jobId, JobState sourceState,
* Helper class representing a rectangle of triads.
*
* @author Donal Fellows
+ * @param width
+ * Width of rectangle, in triads.
+ * @param height
+ * Height of rectangle, in triads.
+ * @param depth
+ * Depth of rectangle. 1 or 3
*/
- private static final class Rectangle {
- final int width;
-
- final int height;
-
- /** Depth of rectangle. 1 or 3 */
- final int depth;
-
- private Rectangle(int width, int height, int depth) {
- this.width = width;
- this.height = height;
- this.depth = depth;
- }
-
+ private record Rectangle(int width, int height, int depth) {
private Rectangle(Row row) {
this(row.getInt("max_width"), row.getInt("max_height"),
TRIAD_DEPTH);
@@ -274,19 +274,9 @@ public synchronized void allocate() {
}
}
- private class Perimeter {
- int boardId;
-
- Direction direction;
-
- Perimeter(Row row) {
- boardId = row.getInt("board_id");
- direction = row.getEnum("direction", Direction.class);
- }
- }
-
/** Encapsulates the queries and updates used in power control. */
- private class PowerSQL extends AbstractSQL {
+ private sealed class PowerSQL extends AbstractSQL
+ permits AllocSQL, DestroySQL {
/** Get basic information about a specific job. */
private final Query getJobState;
@@ -315,7 +305,7 @@ private class PowerSQL extends AbstractSQL {
getJobState = conn.query(GET_JOB);
getJobBoards = conn.query(GET_JOB_BOARDS);
getPerimeter = conn.query(getPerimeterLinks);
- issuePowerChange = conn.update(issueChangeForJob);
+ issuePowerChange = conn.update(ISSUE_CHANGE_FOR_JOB);
setStatePending = conn.update(SET_STATE_PENDING);
setStateDestroyed = conn.update(SET_STATE_DESTROYED);
}
@@ -391,13 +381,13 @@ private final class AllocSQL extends PowerSQL {
AllocSQL(Connection conn) {
super(conn);
bumpImportance = conn.update(BUMP_IMPORTANCE);
- getTasks = conn.query(getAllocationTasks);
+ getTasks = conn.query(GET_ALLOCATION_TASKS);
delete = conn.update(DELETE_TASK);
findFreeBoard = conn.query(FIND_FREE_BOARD);
getRectangles = conn.query(findRectangle);
getRectangleAt = conn.query(findRectangleAt);
countConnectedBoards = conn.query(countConnected);
- findSpecificBoard = conn.query(findLocation);
+ findSpecificBoard = conn.query(FIND_LOCATION);
getConnectedBoardIDs = conn.query(getConnectedBoards);
allocBoard = conn.update(ALLOCATE_BOARDS_BOARD);
allocJob = conn.update(ALLOCATE_BOARDS_JOB);
@@ -448,6 +438,7 @@ public void close() {
}
}
+ /** Encapsulates the task to do a particular allocation. */
private class AllocTask {
final int id;
@@ -531,15 +522,14 @@ Collection allocate(AllocSQL sql) {
* A set of information about the allocations that have been made.
*/
class Allocations {
-
/** The BMPs that have been affected by the allocations. **/
final Set bmps = new HashSet<>();
/** The Machines that have been affected by the allocations. **/
- final Set machines = new HashSet<>();
+ private final Set machines = new HashSet<>();
/** The jobs that have been affected by the allocations. **/
- final List jobIds = new ArrayList<>();
+ private final List jobIds = new ArrayList<>();
Allocations() {
// Does nothing
@@ -595,7 +585,7 @@ private Allocations allocate(Connection conn) {
int maxImportance = -1;
log.trace("Allocate running");
var allocations = new Allocations();
- for (AllocTask task : sql.getTasks.call(AllocTask::new, QUEUED)) {
+ for (var task : sql.getTasks.call(AllocTask::new, QUEUED)) {
if (task.importance > maxImportance) {
maxImportance = task.importance;
} else if (task.importance < maxImportance
@@ -695,22 +685,18 @@ public void tombstone() {
/**
* Describes what the first stage of the tombstoner has copied.
+ *
+ * @param jobs
+ * The jobs that were copied.
+ * @param allocs
+ * The allocations that were copied.
*/
- static final class Copied {
- private final List jobs;
-
- private final List allocs;
-
- private Copied(List jobs, List allocs) {
- this.jobs = jobs;
- this.allocs = allocs;
- }
-
- private Stream allocs() {
+ record Copied(List jobs, List allocs) {
+ private Stream allocStream() {
return allocs.stream().filter(Objects::nonNull);
}
- private Stream jobs() {
+ private Stream jobStream() {
return jobs.stream().filter(Objects::nonNull);
}
@@ -729,100 +715,113 @@ int numJobs() {
int numAllocs() {
return allocs.size();
}
- }
-
- private class HistoricalAlloc {
- int allocId;
- int jobId;
-
- int boardId;
-
- Instant allocTimestamp;
-
- HistoricalAlloc(Row row) {
- allocId = row.getInt("alloc_id");
- jobId = row.getInt("job_id");
- boardId = row.getInt("board_id");
- allocTimestamp = row.getInstant("alloc_timestamp");
- }
+ /**
+ * Details of a copied allocation record.
+ *
+ * @param allocId
+ * Allocation ID
+ * @param jobId
+ * Job ID
+ * @param boardId
+ * Board ID (the board that was allocated)
+ * @param allocTimestamp
+ * When the board was allocated.
+ */
+ record HistoricalAlloc(int allocId, int jobId, int boardId,
+ Instant allocTimestamp) {
+ HistoricalAlloc(Row row) {
+ this(row.getInt("alloc_id"), row.getInt("job_id"),
+ row.getInt("board_id"),
+ row.getInstant("alloc_timestamp"));
+ }
- Object[] args() {
- return new Object[] {
- allocId, jobId, boardId, allocTimestamp
- };
+ private Object[] args() {
+ return new Object[] {
+ allocId, jobId, boardId, allocTimestamp
+ };
+ }
}
- }
-
- private class HistoricalJob {
- int jobId;
-
- int machineId;
-
- String owner;
-
- Instant createTimestamp;
-
- int width;
-
- int height;
-
- int depth;
-
- int allocatedRoot;
-
- Instant keepaliveInterval;
-
- String keepaliveHost;
-
- String deathReason;
-
- Instant deathTimestamp;
-
- byte[] originalRequest;
-
- Instant allocationTimestamp;
- int allocationSize;
-
- String machineName;
-
- String userName;
-
- int groupId;
-
- String groupName;
-
- HistoricalJob(Row row) {
- jobId = row.getInt("job_id");
- machineId = row.getInt("machine_id");
- owner = row.getString("owner");
- createTimestamp = row.getInstant("create_timestamp");
- width = row.getInt("width");
- height = row.getInt("height");
- depth = row.getInt("depth");
- allocatedRoot = row.getInt("allocated_root");
- keepaliveInterval = row.getInstant("keepalive_interval");
- keepaliveHost = row.getString("keepalive_host");
- deathReason = row.getString("death_reason");
- deathTimestamp = row.getInstant("death_timestamp");
- originalRequest = row.getBytes("original_request");
- allocationTimestamp = row.getInstant("allocation_timestamp");
- allocationSize = row.getInt("allocation_size");
- machineName = row.getString("machine_name");
- userName = row.getString("user_name");
- groupId = row.getInt("group_id");
- groupName = row.getString("group_name");
- }
+ /**
+ * Details of a copied job record.
+ *
+ * @param jobId
+ * Job ID
+ * @param machineId
+ * Machine ID
+ * @param owner
+ * Whose job was it (user ID)
+ * @param createTimestamp
+ * When the job was submitted
+ * @param width
+ * Width of requested allocation, in triads
+ * @param height
+ * Height of requested allocation, in triads
+ * @param depth
+ * Depth of requested allocation; 1 (single board) or 3
+ * @param allocatedRoot
+ * ID of board at root of allocation
+ * @param keepaliveInterval
+ * How often keep-alive messages should come
+ * @param keepaliveHost
+ * IP address of machine keeping job alive
+ * @param deathReason
+ * Why did the job terminate?
+ * @param deathTimestamp
+ * When did the job terminate
+ * @param originalRequest
+ * What was actually asked for. (Original request data)
+ * @param allocationTimestamp
+ * When did we complete allocation. Quota consumption was
+ * from this moment to the death timestamp.
+ * @param allocationSize
+ * How many boards were allocated
+ * @param machineName
+ * Name of allocated machine (convenience; implied by machine
+ * ID)
+ * @param userName
+ * Name of user (convenience; implied by owner ID)
+ * @param groupId
+ * Group for accounting purposes
+ * @param groupName
+ * Name of group (convenience; implied by group ID)
+ */
+ record HistoricalJob(int jobId, int machineId, String owner,
+ Instant createTimestamp, int width, int height, int depth,
+ int allocatedRoot, Instant keepaliveInterval,
+ String keepaliveHost, String deathReason,
+ Instant deathTimestamp, byte[] originalRequest,
+ Instant allocationTimestamp, int allocationSize,
+ String machineName, String userName, int groupId,
+ String groupName) {
+ HistoricalJob(Row row) {
+ this(row.getInt("job_id"), row.getInt("machine_id"),
+ row.getString("owner"),
+ row.getInstant("create_timestamp"), row.getInt("width"),
+ row.getInt("height"), row.getInt("depth"),
+ row.getInt("allocated_root"),
+ row.getInstant("keepalive_interval"),
+ row.getString("keepalive_host"),
+ row.getString("death_reason"),
+ row.getInstant("death_timestamp"),
+ row.getBytes("original_request"),
+ row.getInstant("allocation_timestamp"),
+ row.getInt("allocation_size"),
+ row.getString("machine_name"),
+ row.getString("user_name"), row.getInt("group_id"),
+ row.getString("group_name"));
+ }
- Object[] args() {
- return new Object[] {
- jobId, machineId, owner, createTimestamp,
- width, height, depth, allocatedRoot, keepaliveInterval,
- keepaliveHost, deathReason, deathTimestamp, originalRequest,
- allocationTimestamp, allocationSize, machineName, userName,
- groupId, groupName
- };
+ private Object[] args() {
+ return new Object[] {
+ jobId, machineId, owner, createTimestamp, width, height,
+ depth, allocatedRoot, keepaliveInterval, keepaliveHost,
+ deathReason, deathTimestamp, originalRequest,
+ allocationTimestamp, allocationSize, machineName, userName,
+ groupId, groupName
+ };
+ }
}
}
@@ -849,16 +848,17 @@ private Copied tombstone(Connection conn, Connection histConn) {
var writeJobs = histConn.update(WRITE_HISTORICAL_JOBS);
var writeAllocs = histConn.update(WRITE_HISTORICAL_ALLOCS)) {
var grace = historyProps.getGracePeriod();
- var copied = conn.transaction(
- () -> new Copied(readJobs.call(HistoricalJob::new, grace),
- readAllocs.call(HistoricalAlloc::new, grace)));
+ var copied = conn.transaction(() -> new Copied(
+ readJobs.call(Copied.HistoricalJob::new, grace),
+ readAllocs.call(Copied.HistoricalAlloc::new, grace)));
histConn.transaction(() -> {
- copied.allocs().forEach((a) -> writeAllocs.call(a.args()));
- copied.jobs().forEach((j) -> writeJobs.call(j.args()));
+ copied.allocStream().forEach(a -> writeAllocs.call(a.args()));
+ copied.jobStream().forEach(j -> writeJobs.call(j.args()));
});
conn.transaction(() -> {
- copied.allocs().forEach((a) -> deleteAllocs.call(a.allocId));
- copied.jobs().forEach((j) -> deleteJobs.call(j.jobId));
+ copied.allocStream()
+ .forEach(a -> deleteAllocs.call(a.allocId()));
+ copied.jobStream().forEach(j -> deleteJobs.call(j.jobId()));
});
return copied;
}
@@ -905,7 +905,9 @@ private Collection destroyJob(Connection conn, int id,
var bmps = setPower(sql, id, OFF, DESTROYED);
sql.killAlloc.call(id);
sql.markAsDestroyed.call(reason, id);
- log.info("job {} marked as destroyed", id);
+ JobLifecycle.log.info(
+ "destroyed job {}; reclaiming boards in {} frames", id,
+ bmps.size());
return bmps;
} finally {
quotaManager.finishJob(id);
@@ -1060,7 +1062,7 @@ private Collection allocateDimensions(AllocSQL sql,
private int connectedSize(AllocSQL sql, int machineId, TriadCoords root,
int width, int height) {
return sql.countConnectedBoards
- .call1(integer("connected_size"), machineId, root.x, root.y,
+ .call1(integer("connected_size"), machineId, root.x(), root.y(),
width, height).orElse(-1);
}
@@ -1152,10 +1154,11 @@ private Collection allocateTriadsAt(AllocSQL sql, int jobId,
private Collection setAllocation(AllocSQL sql, int jobId,
Rectangle rect, int machineId, TriadCoords root) {
log.debug("performing allocation for {}: {}x{}x{} at {}:{}:{}", jobId,
- rect.width, rect.height, rect.depth, root.x, root.y, root.z);
- var boardsToAllocate = sql.getConnectedBoardIDs
- .call(integer("board_id"), machineId, root.x, root.y, root.z,
- rect.width, rect.height, rect.depth);
+ rect.width, rect.height, rect.depth, root.x(), root.y(),
+ root.z());
+ var boardsToAllocate = sql.getConnectedBoardIDs.call(
+ integer("board_id"), machineId, root.x(), root.y(), root.z(),
+ rect.width, rect.height, rect.depth);
if (boardsToAllocate.isEmpty()) {
log.debug("No boards to allocate");
return List.of();
@@ -1233,6 +1236,13 @@ private Collection setPower(PowerSQL sql, int jobId,
// Number of changes pending, one per board
int numPending = 0;
+ record Perimeter(int boardId, Direction direction) {
+ Perimeter(Row row) {
+ this(row.getInt("board_id"),
+ row.getEnum("direction", Direction.class));
+ }
+ }
+
var bmps = new HashSet();
if (power == ON) {
/*
@@ -1241,10 +1251,10 @@ private Collection setPower(PowerSQL sql, int jobId,
* switched off because they are links to boards that are not
* allocated to the job. Off-board links are shut off by default.
*/
- var perimeterLinks = Row.stream(
- sql.getPerimeter.call(Perimeter::new, jobId))
- .toCollectingMap(Direction.class, (p) -> p.boardId,
- (p) -> p.direction);
+ var perimeterLinks =
+ Row.stream(sql.getPerimeter.call(Perimeter::new, jobId))
+ .toCollectingMap(Direction.class,
+ Perimeter::boardId, Perimeter::direction);
for (var board : boards) {
var toChange = perimeterLinks.getOrDefault(board.boardId,
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Epochs.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Epochs.java
index 5d587f3c2d..6d19209cb5 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Epochs.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Epochs.java
@@ -20,26 +20,21 @@
import java.time.Duration;
import java.util.Collection;
-import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
-import java.util.function.BiConsumer;
-
-import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
+import jakarta.annotation.PostConstruct;
import com.google.errorprone.annotations.concurrent.GuardedBy;
-import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly;
-
/**
* Manages waiting for values.
*
@@ -195,7 +190,7 @@ public void blacklistChanged(int board) {
* @author Donal Fellows
* @author Andrew Rowley
*/
- public final class Epoch {
+ public static final class Epoch {
private final EpochMap map;
private final List ids;
@@ -288,10 +283,8 @@ synchronized boolean checkEmptyValues() {
void changed(int id) {
var items = getSet(id);
if (nonNull(items)) {
- synchronized (items) {
- for (var item : items) {
- item.updateChanged(id);
- }
+ for (var item : items) {
+ item.updateChanged(id);
}
}
}
@@ -303,9 +296,6 @@ void changed(int id) {
* The key into the map.
* @return The removed set of epochs. Empty if the key is absent.
*/
- @UsedInJavadocOnly({
- BiConsumer.class, ConcurrentModificationException.class
- })
private synchronized Set getSet(Integer id) {
var weakmap = map.get(id);
if (weakmap == null) {
@@ -318,7 +308,7 @@ private synchronized Set getSet(Integer id) {
synchronized void addAll(Epochs.Epoch epoch, List ids) {
for (var id : ids) {
- map.computeIfAbsent(id, key -> new WeakHashMap<>()).put(epoch, OBJ);
+ map.computeIfAbsent(id, __ -> new WeakHashMap<>()).put(epoch, OBJ);
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/ProxyRememberer.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/ProxyRememberer.java
index 298a56e79a..4d9c3cc01c 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/ProxyRememberer.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/ProxyRememberer.java
@@ -22,12 +22,11 @@
import java.util.List;
import java.util.Map;
-import javax.annotation.PreDestroy;
-
import org.springframework.stereotype.Component;
import com.google.errorprone.annotations.concurrent.GuardedBy;
+import jakarta.annotation.PreDestroy;
import uk.ac.manchester.spinnaker.alloc.proxy.ProxyCore;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManager.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManager.java
index e5cd3af4d8..cdfc2f9b7a 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManager.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManager.java
@@ -27,8 +27,8 @@
import java.util.List;
import java.util.Optional;
-import javax.annotation.PostConstruct;
-import javax.ws.rs.BadRequestException;
+import jakarta.annotation.PostConstruct;
+import jakarta.ws.rs.BadRequestException;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -210,25 +210,14 @@ public Optional addQuota(int groupId, int delta) {
* operation.
*
* @author Donal Fellows
+ * @param name
+ * The name of the group.
+ * @param quota
+ * The new quota of the group.
*/
- public static final class AdjustedQuota {
- private final String name;
-
- private final Long quota;
-
+ public record AdjustedQuota(String name, Long quota) {
private AdjustedQuota(Row row) {
- this.name = row.getString("group_name");
- this.quota = row.getLong("quota");
- }
-
- /** @return The name of the group. */
- public String getName() {
- return name;
- }
-
- /** @return The new quota of the group. */
- public Long getQuota() {
- return quota;
+ this(row.getString("group_name"), row.getLong("quota"));
}
}
@@ -240,6 +229,7 @@ private final class AdjustQuotaSQL extends AbstractSQL {
@Override
public void close() {
adjustQuota.close();
+ getQuota.close();
super.close();
}
@@ -278,7 +268,7 @@ private void doConsolidate(Connection c) {
}
}
- private class ConsolidateSQL extends AbstractSQL {
+ private final class ConsolidateSQL extends AbstractSQL {
private final Query getConsoldationTargets =
conn.query(GET_CONSOLIDATION_TARGETS);
@@ -322,17 +312,13 @@ private class Target {
}
}
- private static class QuotaInfo {
- /** The size of quota remaining, in board-seconds. */
- final long quota;
-
- /** The units that the quota was measured in on the NMPI. */
- final String units;
-
- QuotaInfo(long quota, String units) {
- this.quota = quota;
- this.units = units;
- }
+ /**
+ * @param quota
+ * The size of quota remaining, in board-seconds.
+ * @param units
+ * The units that the quota was measured in on the NMPI.
+ */
+ private record QuotaInfo(long quota, String units) {
}
private QuotaInfo parseQuotaData(List projects) {
@@ -371,16 +357,16 @@ final Optional mayCreateNMPISession(String collab) {
var projects = nmpi.getProjects(STATUS_ACCEPTED, collab);
var info = parseQuotaData(projects);
- log.debug("Setting quota of collab {} to {}", collab, info.quota);
+ log.debug("Setting quota of collab {} to {}", collab, info.quota());
// Update quota in group for collab from NMPI
try (var c = getConnection();
var setQuota = c.update(SET_COLLAB_QUOTA)) {
- c.transaction(() -> setQuota.call(info.quota, collab));
+ c.transaction(() -> setQuota.call(info.quota(), collab));
}
- if (info.quota > 0) {
- return Optional.of(info.units);
+ if (info.quota() > 0) {
+ return Optional.of(info.units());
}
return Optional.empty();
}
@@ -489,17 +475,13 @@ final Optional mayUseNMPIJob(String user,
new NMPIJobQuotaDetails(job.getCollab(), quotaUnits.get()));
}
- static final class NMPIJobQuotaDetails {
- /** The collaboratory ID. */
- final String collabId;
-
- /** The units of the Quota. */
- final String quotaUnits;
-
- private NMPIJobQuotaDetails(String collabId, String quotaUnits) {
- this.collabId = collabId;
- this.quotaUnits = quotaUnits;
- }
+ /**
+ * @param collabId
+ * The collaboratory ID.
+ * @param quotaUnits
+ * The units of the Quota.
+ */
+ record NMPIJobQuotaDetails(String collabId, String quotaUnits) {
}
void associateNMPIJob(int jobId, int nmpiJobId, String quotaUnits) {
@@ -511,12 +493,8 @@ void associateNMPIJob(int jobId, int nmpiJobId, String quotaUnits) {
}
/** Results of database queries. */
- private static final class FinishInfo {
- Optional quota;
-
- Optional session;
-
- Optional job;
+ private record FinishInfo(Optional quota, Optional session,
+ Optional job) {
}
private FinishInfo getFinishingInfo(int jobId) {
@@ -525,13 +503,11 @@ private FinishInfo getFinishingInfo(int jobId) {
var getNMPIJob = c.query(GET_JOB_NMPI_JOB);
var getUsage = c.query(GET_JOB_USAGE_AND_QUOTA)) {
// Get the quota used
- return c.transaction(false, () -> {
- var i = new FinishInfo();
- i.quota = getUsage.call1(r -> r.getLong("quota_used"), jobId);
- i.session = getSession.call1(Session::new, jobId);
- i.job = getNMPIJob.call1(NMPIJob::new, jobId);
- return i;
- });
+ return c.transaction(false,
+ () -> new FinishInfo(
+ getUsage.call1(r -> r.getLong("quota_used"), jobId),
+ getSession.call1(Session::new, jobId),
+ getNMPIJob.call1(NMPIJob::new, jobId)));
}
}
@@ -541,16 +517,17 @@ final void finishJob(int jobId) {
// From here on, we don't touch the DB but we do touch the network
- if (!info.quota.isPresent()) {
+ if (!info.quota().isPresent()) {
// No quota? No update!
return;
}
// If job has associated session, update quota in session
- info.session.ifPresent(session -> {
+ info.session().ifPresent(session -> {
try {
- nmpi.setSessionStatusAndResources(session.id, "finished",
- getResourceUsage(info.quota.get(), session.quotaUnits));
+ nmpi.setSessionStatusAndResources(session.id(), "finished",
+ getResourceUsage(info.quota().get(),
+ session.quotaUnits()));
} catch (BadRequestException e) {
log.error(e.getResponse().readEntity(String.class));
throw e;
@@ -558,10 +535,10 @@ final void finishJob(int jobId) {
});
// If job has associated NMPI job, update quota on NMPI job
- info.job.ifPresent(nmpiJob -> {
+ info.job().ifPresent(nmpiJob -> {
try {
- nmpi.setJobResources(nmpiJob.id,
- getResourceUsage(info.quota.get(), nmpiJob.quotaUnits));
+ nmpi.setJobResources(nmpiJob.id(), getResourceUsage(
+ info.quota().get(), nmpiJob.quotaUnits()));
} catch (BadRequestException e) {
log.error(e.getResponse().readEntity(String.class));
throw e;
@@ -569,25 +546,15 @@ final void finishJob(int jobId) {
});
}
- private static final class Session {
- private int id;
-
- private String quotaUnits;
-
+ private record Session(int id, String quotaUnits) {
private Session(Row r) {
- this.id = r.getInt("session_id");
- this.quotaUnits = r.getString("quota_units");
+ this(r.getInt("session_id"), r.getString("quota_units"));
}
}
- private static final class NMPIJob {
- private int id;
-
- private String quotaUnits;
-
+ private record NMPIJob(int id, String quotaUnits) {
private NMPIJob(Row r) {
- this.id = r.getInt("nmpi_job_id");
- this.quotaUnits = r.getString("quota_units");
+ this(r.getInt("nmpi_job_id"), r.getString("quota_units"));
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java
index b831a0e7f5..11a1d2ad44 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java
@@ -32,10 +32,10 @@
import static uk.ac.manchester.spinnaker.alloc.model.JobState.READY;
import static uk.ac.manchester.spinnaker.alloc.model.PowerState.OFF;
import static uk.ac.manchester.spinnaker.alloc.model.PowerState.ON;
-import static uk.ac.manchester.spinnaker.alloc.security.SecurityConfig.MAY_SEE_JOB_DETAILS;
import static uk.ac.manchester.spinnaker.utils.CollectionUtils.copy;
import static uk.ac.manchester.spinnaker.utils.OptionalUtils.apply;
+import java.io.Serial;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -50,7 +50,6 @@
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PostFilter;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -362,7 +361,6 @@ private static JobListEntryRecord makeJobListEntryRecord(Permit permit,
}
@Override
- @PostFilter(MAY_SEE_JOB_DETAILS)
public Optional getJob(Permit permit, int id) {
return executeRead(conn -> getJob(id, conn).map(j -> (Job) j));
}
@@ -374,7 +372,6 @@ private Optional getJob(int id, Connection conn) {
}
@Override
- @PostFilter(MAY_SEE_JOB_DETAILS)
public Optional getJobInfo(Permit permit, int id) {
return executeRead(conn -> {
try (var s = conn.query(GET_JOB);
@@ -563,7 +560,7 @@ public Optional createJobForNMPIJob(String owner, int nmpiJobId,
var quotaDetails = collab.get();
var job = execute(conn -> createJobInGroup(
- owner, quotaDetails.collabId, descriptor, machineName,
+ owner, quotaDetails.collabId(), descriptor, machineName,
tags, keepaliveInterval, originalRequest));
// On failure to get job, just return; shouldn't happen as quota checked
// earlier, but just in case!
@@ -572,7 +569,7 @@ public Optional createJobForNMPIJob(String owner, int nmpiJobId,
}
quotaManager.associateNMPIJob(job.get().getId(), nmpiJobId,
- quotaDetails.quotaUnits);
+ quotaDetails.quotaUnits());
// Return the job created
return job;
@@ -626,17 +623,6 @@ private static Optional getUser(Connection conn, String userName) {
}
}
- private class BoardLocated {
- int boardId;
-
- int z;
-
- BoardLocated(Row row) {
- boardId = row.getInt("board_id");
- z = row.getInt("z");
- }
- }
-
/**
* Resolve a machine name and {@link HasBoardCoords} to a board identifier.
*
@@ -655,20 +641,26 @@ private class BoardLocated {
*/
private Integer locateBoard(Connection conn, String machineName,
HasBoardCoords b, boolean requireTriadRoot) {
+ record BoardLocated(int boardId, int z) {
+ BoardLocated(Row row) {
+ this(row.getInt("board_id"), row.getInt("z"));
+ }
+ }
+
try (var findTriad = conn.query(FIND_BOARD_BY_NAME_AND_XYZ);
var findPhysical = conn.query(FIND_BOARD_BY_NAME_AND_CFB);
var findIP = conn.query(FIND_BOARD_BY_NAME_AND_IP_ADDRESS)) {
if (nonNull(b.triad)) {
return findTriad.call1(BoardLocated::new,
- machineName, b.triad.x, b.triad.y, b.triad.z)
+ machineName, b.triad.x(), b.triad.y(), b.triad.z())
.filter(board -> !requireTriadRoot || board.z == 0)
.map(board -> board.boardId)
.orElseThrow(() -> new IllegalArgumentException(
NO_BOARD_MSG));
} else if (nonNull(b.physical)) {
return findPhysical.call1(
- BoardLocated::new, machineName, b.physical.c,
- b.physical.f, b.physical.b)
+ BoardLocated::new, machineName, b.physical.c(),
+ b.physical.f(), b.physical.b())
.filter(board -> !requireTriadRoot || board.z == 0)
.map(board -> board.boardId)
.orElseThrow(() -> new IllegalArgumentException(
@@ -723,8 +715,7 @@ private static String mergeDescription(HasChipLocation coreLocation,
if (isNull(description)) {
description = "";
}
- if (coreLocation instanceof HasCoreLocation) {
- var loc = (HasCoreLocation) coreLocation;
+ if (coreLocation instanceof HasCoreLocation loc) {
description += format(" (at core %d of chip %s)", loc.getP(),
loc.asChipLocation());
} else if (nonNull(coreLocation)) {
@@ -734,14 +725,9 @@ private static String mergeDescription(HasChipLocation coreLocation,
return description;
}
- private class Problem {
- int boardId;
-
- Integer jobId;
-
+ private record Problem(int boardId, Integer jobId) {
Problem(Row row) {
- boardId = row.getInt("board_id");
- jobId = row.getInt("job_id");
+ this(row.getInt("board_id"), row.getInt("job_id"));
}
}
@@ -784,28 +770,13 @@ private Optional reportProblem(Problem problem,
});
}
- private class Reported {
- int boardId;
-
- int x;
-
- int y;
-
- int z;
-
- String address;
-
- int numReports;
-
+ private record Reported(int boardId, int x, int y, int z, String address,
+ int numReports) {
Reported(Row row) {
- boardId = row.getInt("board_id");
- x = row.getInt("x");
- y = row.getInt("y");
- z = row.getInt("z");
- address = row.getString("address");
- numReports = row.getInt("numReports");
+ this(row.getInt("board_id"), row.getInt("x"), row.getInt("y"),
+ row.getInt("z"), row.getString("address"),
+ row.getInt("numReports"));
}
-
}
/**
@@ -847,7 +818,7 @@ private static DownLink makeDownLinkFromRow(Row row) {
board2, row.getEnum("dir_2", Direction.class));
}
- private class MachineImpl implements Machine {
+ private final class MachineImpl implements Machine {
private final int id;
private final boolean inService;
@@ -903,14 +874,16 @@ public boolean waitForChange(Duration timeout) {
}
}
+ private BoardLocation boardLoc(Row row) {
+ return new BoardLocationImpl(row, this);
+ }
+
@Override
public Optional getBoardByChip(HasChipLocation chip) {
try (var conn = getConnection();
var findBoard = conn.query(findBoardByGlobalChip)) {
- return conn.transaction(false,
- () -> findBoard.call1(
- row -> new BoardLocationImpl(row, this), id,
- chip.getX(), chip.getY()));
+ return conn.transaction(false, () -> findBoard
+ .call1(this::boardLoc, id, chip.getX(), chip.getY()));
}
}
@@ -920,9 +893,8 @@ public Optional getBoardByPhysicalCoords(
try (var conn = getConnection();
var findBoard = conn.query(findBoardByPhysicalCoords)) {
return conn.transaction(false,
- () -> findBoard.call1(
- row -> new BoardLocationImpl(row, this), id,
- coords.c, coords.f, coords.b));
+ () -> findBoard.call1(this::boardLoc, id, coords.c(),
+ coords.f(), coords.b()));
}
}
@@ -932,9 +904,8 @@ public Optional getBoardByLogicalCoords(
try (var conn = getConnection();
var findBoard = conn.query(findBoardByLogicalCoords)) {
return conn.transaction(false,
- () -> findBoard.call1(
- row -> new BoardLocationImpl(row, this), id,
- coords.x, coords.y, coords.z));
+ () -> findBoard.call1(this::boardLoc, id, coords.x(),
+ coords.y(), coords.z()));
}
}
@@ -943,9 +914,7 @@ public Optional getBoardByIPAddress(String address) {
try (var conn = getConnection();
var findBoard = conn.query(findBoardByIPAddress)) {
return conn.transaction(false,
- () -> findBoard.call1(
- row -> new BoardLocationImpl(row, this), id,
- address));
+ () -> findBoard.call1(this::boardLoc, id, address));
}
}
@@ -953,8 +922,10 @@ public Optional getBoardByIPAddress(String address) {
public String getRootBoardBMPAddress() {
try (var conn = getConnection();
var rootBMPaddr = conn.query(GET_ROOT_BMP_ADDRESS)) {
- return conn.transaction(false, () -> rootBMPaddr.call1(
- string("address"), id).orElse(null));
+ return conn
+ .transaction(false,
+ () -> rootBMPaddr.call1(string("address"), id))
+ .orElse(null);
}
}
@@ -998,7 +969,7 @@ public List getDownLinks() {
}
}
try (var conn = getConnection();
- var boardNumbers = conn.query(getDeadLinks)) {
+ var boardNumbers = conn.query(GET_DEAD_LINKS)) {
var downLinks = conn.transaction(false, () -> boardNumbers
.call(Spalloc::makeDownLinkFromRow, id));
synchronized (Spalloc.this) {
@@ -1052,10 +1023,11 @@ public boolean isInService() {
public String getBMPAddress(BMPCoords bmp) {
try (var conn = getConnection();
var bmpAddr = conn.query(GET_BMP_ADDRESS)) {
- return conn.transaction(false,
- () -> bmpAddr
- .call1(string("address"), id, bmp.getCabinet(),
- bmp.getFrame()).orElse(null));
+ return conn
+ .transaction(false,
+ () -> bmpAddr.call1(string("address"), id,
+ bmp.cabinet(), bmp.frame()))
+ .orElse(null);
}
}
@@ -1064,17 +1036,15 @@ public List getBoardNumbers(BMPCoords bmp) {
try (var conn = getConnection();
var boardNumbers = conn.query(GET_BMP_BOARD_NUMBERS)) {
return conn.transaction(false,
- () -> boardNumbers
- .call(integer("board_num"), id,
- bmp.getCabinet(), bmp.getFrame()));
+ () -> boardNumbers.call(integer("board_num"), id,
+ bmp.cabinet(), bmp.frame()));
}
}
@Override
public boolean equals(Object other) {
// Equality is defined exactly by the database ID
- return (other instanceof MachineImpl)
- && (id == ((MachineImpl) other).id);
+ return (other instanceof MachineImpl m) && (id == m.id);
}
@Override
@@ -1191,7 +1161,7 @@ private final class BoardReportSQL extends AbstractSQL {
final Update insertReport = conn.update(INSERT_BOARD_REPORT);
- final Query getReported = conn.query(getReportedBoards);
+ final Query getReported = conn.query(GET_REPORTED_BOARDS);
final Update setFunctioning = conn.update(SET_FUNCTIONING_FIELD);
@@ -1236,24 +1206,24 @@ void header(String issue, int numBoards, String who) {
void chip(ReportedBoard board) {
b.format("\tBoard for job (%d) chip %s\n", //
- id, board.chip);
+ id, board.chip());
}
void triad(ReportedBoard board) {
b.format("\tBoard for job (%d) board (X:%d,Y:%d,Z:%d)\n", //
- id, board.x, board.y, board.z);
+ id, board.x(), board.y(), board.z());
}
void phys(ReportedBoard board) {
b.format(
"\tBoard for job (%d) board "
+ "[Cabinet:%d,Frame:%d,Board:%d]\n", //
- id, board.cabinet, board.frame, board.board);
+ id, board.cabinet(), board.frame(), board.board());
}
void ip(ReportedBoard board) {
b.format("\tBoard for job (%d) board (IP: %s)\n", //
- id, board.address);
+ id, board.address());
}
void issue(int issueId) {
@@ -1487,9 +1457,9 @@ public String reportIssue(IssueReportRequest report, Permit permit) {
var result = q.transaction(
() -> reportIssue(report, permit, email, q));
emailSender.sendServiceMail(email);
- for (var m : report.boards.stream()
+ for (var m : report.boards().stream()
.map(b -> q.getNamedMachine.call1(
- r -> r.getInt("machine_id"), b.machine, true))
+ r -> r.getInt("machine_id"), b.machine(), true))
.collect(toSet())) {
if (m.isPresent()) {
epochs.machineChanged(m.get());
@@ -1525,13 +1495,13 @@ public String reportIssue(IssueReportRequest report, Permit permit) {
*/
private String reportIssue(IssueReportRequest report, Permit permit,
EmailBuilder email, BoardReportSQL q) throws ReportRollbackExn {
- email.header(report.issue, report.boards.size(), permit.name);
+ email.header(report.issue(), report.boards().size(), permit.name);
int userId = getUser(q.getConnection(), permit.name)
.orElseThrow(() -> new ReportRollbackExn(
"no such user: %s", permit.name));
- for (var board : report.boards) {
+ for (var board : report.boards()) {
addIssueReport(q, getJobBoardForReport(q, board, email),
- report.issue, userId, email);
+ report.issue(), userId, email);
}
return takeBoardsOutOfService(q, email).map(acted -> {
email.footer(acted);
@@ -1555,46 +1525,47 @@ private String reportIssue(IssueReportRequest report, Permit permit,
private int getJobBoardForReport(BoardReportSQL q, ReportedBoard board,
EmailBuilder email) throws ReportRollbackExn {
Problem r;
- if (nonNull(board.chip)) {
+ if (nonNull(board.chip())) {
r = q.findBoardByChip
- .call1(Problem::new, id, root, board.chip.getX(),
- board.chip.getY())
- .orElseThrow(() -> new ReportRollbackExn(board.chip));
+ .call1(Problem::new, id, root, board.chip().getX(),
+ board.chip().getY())
+ .orElseThrow(() -> new ReportRollbackExn(board.chip()));
email.chip(board);
- } else if (nonNull(board.x)) {
+ } else if (nonNull(board.x())) {
r = q.findBoardByTriad
- .call1(Problem::new, machineId, board.x, board.y,
- board.z)
+ .call1(Problem::new, machineId, board.x(), board.y(),
+ board.z())
.orElseThrow(() -> new ReportRollbackExn(
- "triad (%s,%s,%s) not in machine", board.x,
- board.y, board.z));
+ "triad (%s,%s,%s) not in machine", board.x(),
+ board.y(), board.z()));
if (isNull(r.jobId) || id != r.jobId) {
throw new ReportRollbackExn(
- "triad (%s,%s,%s) not allocated to job %d", board.x,
- board.y, board.z, id);
+ "triad (%s,%s,%s) not allocated to job %d",
+ board.x(), board.y(), board.z(), id);
}
email.triad(board);
- } else if (nonNull(board.cabinet)) {
+ } else if (nonNull(board.cabinet())) {
r = q.findBoardPhys
- .call1(Problem::new, machineId, board.cabinet,
- board.frame, board.board)
+ .call1(Problem::new, machineId, board.cabinet(),
+ board.frame(), board.board())
.orElseThrow(() -> new ReportRollbackExn(
"physical board [%s,%s,%s] not in machine",
- board.cabinet, board.frame, board.board));
+ board.cabinet(), board.frame(), board.board()));
if (isNull(r.jobId) || id != r.jobId) {
throw new ReportRollbackExn(
"physical board [%s,%s,%s] not allocated to job %d",
- board.cabinet, board.frame, board.board, id);
+ board.cabinet(), board.frame(), board.board(), id);
}
email.phys(board);
- } else if (nonNull(board.address)) {
- r = q.findBoardNet.call1(Problem::new, machineId, board.address)
+ } else if (nonNull(board.address())) {
+ r = q.findBoardNet
+ .call1(Problem::new, machineId, board.address())
.orElseThrow(() -> new ReportRollbackExn(
- "board at %s not in machine", board.address));
+ "board at %s not in machine", board.address()));
if (isNull(r.jobId) || id != r.jobId) {
throw new ReportRollbackExn(
"board at %s not allocated to job %d",
- board.address, id);
+ board.address(), id);
}
email.ip(board);
} else {
@@ -1666,7 +1637,7 @@ public void forgetProxy(ProxyCore proxy) {
@Override
public boolean equals(Object other) {
// Equality is defined exactly by the database ID
- return (other instanceof JobImpl) && (id == ((JobImpl) other).id);
+ return (other instanceof JobImpl j) && (id == j.id);
}
@Override
@@ -1906,6 +1877,7 @@ public Job getJob() {
}
static class PartialJobException extends IllegalStateException {
+ @Serial
private static final long serialVersionUID = 2997856394666135483L;
PartialJobException() {
@@ -1929,6 +1901,7 @@ class ReportRollbackExn extends RuntimeException {
}
abstract class GroupsException extends RuntimeException {
+ @Serial
private static final long serialVersionUID = 6607077117924279611L;
GroupsException(String message) {
@@ -1941,6 +1914,7 @@ abstract class GroupsException extends RuntimeException {
}
class NoSuchGroupException extends GroupsException {
+ @Serial
private static final long serialVersionUID = 5193818294198205503L;
@FormatMethod
@@ -1950,6 +1924,7 @@ class NoSuchGroupException extends GroupsException {
}
class MultipleGroupsException extends GroupsException {
+ @Serial
private static final long serialVersionUID = 6284332340565334236L;
@FormatMethod
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocAPI.java
index 1dcedfed35..ced3655fd3 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocAPI.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocAPI.java
@@ -31,17 +31,16 @@
import java.util.Optional;
import java.util.Set;
-import javax.validation.Valid;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.PositiveOrZero;
-
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import com.google.errorprone.annotations.Keep;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.PositiveOrZero;
import uk.ac.manchester.spinnaker.alloc.compat.V1CompatService;
import uk.ac.manchester.spinnaker.alloc.model.BoardCoords;
import uk.ac.manchester.spinnaker.alloc.model.ConnectionInfo;
@@ -328,7 +327,8 @@ void reportProblem(@IPAddress String address, HasChipLocation coreLocation,
* @see CreateDimensionsAt
* @see CreateBoard
*/
- abstract class CreateDescriptor {
+ abstract sealed class CreateDescriptor
+ permits CreateDimensions, CreateNumBoards, HasBoardCoords {
/**
* The maximum number of dead boards tolerated in the allocation.
* Ignored when asking for a single board.
@@ -449,7 +449,8 @@ public int getArea() {
}
/** Some requests have the locations of boards. */
- abstract class HasBoardCoords extends CreateDescriptor {
+ abstract sealed class HasBoardCoords
+ extends CreateDescriptor permits CreateDimensionsAt, CreateBoard {
/** The logical coordinates, or {@code null}. */
@Valid
public final TriadCoords triad;
@@ -763,7 +764,9 @@ interface CreateVisitor {
* The descriptor.
* @return The result of the visiting.
*/
- T numBoards(@NotNull CreateNumBoards createNumBoards);
+ default T numBoards(@NotNull CreateNumBoards createNumBoards) {
+ return null;
+ }
/**
* Visit a descriptor.
@@ -772,7 +775,9 @@ interface CreateVisitor {
* The descriptor.
* @return The result of the visiting.
*/
- T dimensionsAt(@NotNull CreateDimensionsAt createDimensionsAt);
+ default T dimensionsAt(@NotNull CreateDimensionsAt createDimensionsAt) {
+ return null;
+ }
/**
* Visit a descriptor.
@@ -781,7 +786,9 @@ interface CreateVisitor {
* The descriptor.
* @return The result of the visiting.
*/
- T dimensions(@NotNull CreateDimensions createDimensions);
+ default T dimensions(@NotNull CreateDimensions createDimensions) {
+ return null;
+ }
/**
* Visit a descriptor.
@@ -790,7 +797,9 @@ interface CreateVisitor {
* The descriptor.
* @return The result of the visiting.
*/
- T board(@NotNull CreateBoard createBoard);
+ default T board(@NotNull CreateBoard createBoard) {
+ return null;
+ }
}
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BMPController.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BMPController.java
index f3fe15f957..3019eec87c 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BMPController.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BMPController.java
@@ -18,6 +18,7 @@
import static java.lang.String.format;
import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;
+import static java.time.Instant.now;
import static java.util.Objects.requireNonNull;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.alloc.bmp.NonBootOperation.GET_SERIAL;
@@ -30,7 +31,6 @@
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
-import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -41,8 +41,6 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -54,6 +52,7 @@
import com.google.errorprone.annotations.RestrictedApi;
import com.google.errorprone.annotations.concurrent.GuardedBy;
+import jakarta.annotation.PostConstruct;
import uk.ac.manchester.spinnaker.alloc.ForTestingOnly;
import uk.ac.manchester.spinnaker.alloc.ServiceMasterControl;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AllocatorProperties;
@@ -217,7 +216,7 @@ public void triggerSearch(Collection bmps) {
for (var b : bmps) {
var worker = workers.get(b);
if (worker != null) {
- scheduler.schedule(() -> worker.run(), Instant.now());
+ scheduler.schedule(worker::run, now());
} else {
log.error("Could not find worker for BMP {}", b);
}
@@ -229,7 +228,8 @@ private interface ThrowingAction {
void act() throws ProcessException, IOException, InterruptedException;
}
- private abstract class Request {
+ private abstract sealed class Request
+ permits BoardRequest, PowerRequest {
final int bmpId;
private int numTries = 0;
@@ -455,15 +455,15 @@ private final class PowerRequest extends Request {
List powerChanges) {
super(bmpId);
for (var change : powerChanges) {
- if (change.power) {
- powerOnBoards.add(new BMPBoard(change.boardNum));
+ if (change.power()) {
+ powerOnBoards.add(new BMPBoard(change.boardNum()));
} else {
- powerOffBoards.add(new BMPBoard(change.boardNum));
+ powerOffBoards.add(new BMPBoard(change.boardNum()));
}
- change.offLinks.stream().forEach(link ->
- linkRequests.add(new Link(change.boardNum, link)));
- changeIds.add(change.changeId);
- boardToId.put(change.boardNum, change.boardId);
+ change.offLinks().stream().forEach(link ->
+ linkRequests.add(new Link(change.boardNum(), link)));
+ changeIds.add(change.changeId());
+ boardToId.put(change.boardNum(), change.boardId);
}
this.jobId = jobId;
this.from = from;
@@ -674,7 +674,7 @@ private Optional getBoardId(HasBMPLocation addr) {
}
private Integer getBoardId(BMPBoard board) {
- return boardToId.get(board.board);
+ return boardToId.get(board.board());
}
}
@@ -845,20 +845,11 @@ boolean tryProcessRequest(SpiNNakerControl controller)
throws InterruptedException {
return bmpAction(() -> {
switch (op) {
- case WRITE_BL:
- writeBlacklist(controller);
- break;
- case READ_BL:
- readBlacklist(controller);
- break;
- case GET_SERIAL:
- readSerial(controller);
- break;
- case READ_TEMP:
- readTemps(controller);
- break;
- default:
- throw new IllegalArgumentException();
+ case WRITE_BL -> writeBlacklist(controller);
+ case READ_BL -> readBlacklist(controller);
+ case GET_SERIAL -> readSerial(controller);
+ case READ_TEMP -> readTemps(controller);
+ default -> throw new IllegalArgumentException();
}
epochs.blacklistChanged(boardId);
epochs.machineChanged(machineId);
@@ -987,34 +978,20 @@ public String toString() {
}
}
- private class PowerChange {
- final Integer changeId;
-
- final int jobId;
-
- final Integer boardId;
-
- final Integer boardNum;
-
- final boolean power;
-
- final JobState from;
-
- final JobState to;
-
- final List offLinks;
-
+ private record PowerChange(Integer changeId, int jobId, Integer boardId,
+ Integer boardNum, boolean power, JobState from, JobState to,
+ List offLinks) {
PowerChange(Row row) {
- changeId = row.getInteger("change_id");
- jobId = row.getInt("job_id");
- boardId = row.getInteger("board_id");
- boardNum = row.getInteger("board_num");
- power = row.getBoolean("power");
- from = row.getEnum("from_state", JobState.class);
- to = row.getEnum("to_state", JobState.class);
- offLinks = List.of(Direction.values()).stream().filter(
- link -> !row.getBoolean(link.columnName)).collect(
- Collectors.toList());
+ this(row.getInteger("change_id"), //
+ row.getInt("job_id"), //
+ row.getInteger("board_id"), //
+ row.getInteger("board_num"), //
+ row.getBoolean("power"),
+ row.getEnum("from_state", JobState.class),
+ row.getEnum("to_state", JobState.class),
+ List.of(Direction.values()).stream()
+ .filter(link -> !row.getBoolean(link.columnName))
+ .collect(Collectors.toList()));
}
boolean isSameJob(PowerChange p) {
@@ -1086,8 +1063,8 @@ private List getRequestedOperations() {
}
if (!jobChanges.isEmpty()) {
log.debug("Running job changes {}", jobChanges);
- requests.add(new PowerRequest(bmpId, change.jobId,
- change.from, change.to, jobChanges));
+ requests.add(new PowerRequest(bmpId, change.jobId(),
+ change.from(), change.to(), jobChanges));
}
}
@@ -1164,15 +1141,13 @@ void processRequests(long millis)
throws IOException, SpinnmanException, InterruptedException;
/**
- * Get the last BMP exception.
+ * Get the most recently thrown BMP processing exception.
*
- * @return The exception.
+ * @return Current processing exception.
*/
Throwable getBmpException();
- /**
- * Clear the last BMP exception.
- */
+ /** Clear the current processing exception. */
void clearBmpException();
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStore.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStore.java
index 362f74120b..c652a9cd2d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStore.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStore.java
@@ -34,6 +34,7 @@
import uk.ac.manchester.spinnaker.alloc.db.DatabaseAwareBean;
import uk.ac.manchester.spinnaker.alloc.db.Row;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
+import uk.ac.manchester.spinnaker.machine.CoreLocation;
import uk.ac.manchester.spinnaker.machine.Direction;
import uk.ac.manchester.spinnaker.messages.model.Blacklist;
@@ -61,17 +62,6 @@ public Optional readBlacklist(int boardId) {
return executeRead(conn -> readBlacklist(conn, boardId));
}
- private class DeadLink {
- ChipLocation location;
-
- Direction direction;
-
- DeadLink(Row row) {
- location = new ChipLocation(row.getInt("x"), row.getInt("y"));
- direction = row.getEnum("direction", Direction.class);
- }
- }
-
/**
* Read a blacklist from the database.
*
@@ -84,6 +74,13 @@ private class DeadLink {
* If database access fails.
*/
private Optional readBlacklist(Connection conn, int boardId) {
+ record DeadLink(ChipLocation location, Direction direction) {
+ DeadLink(Row row) {
+ this(new ChipLocation(row.getInt("x"), row.getInt("y")),
+ row.getEnum("direction", Direction.class));
+ }
+ }
+
try (var blChips = conn.query(GET_BLACKLISTED_CHIPS);
var blCores = conn.query(GET_BLACKLISTED_CORES);
var blLinks = conn.query(GET_BLACKLISTED_LINKS)) {
@@ -91,14 +88,12 @@ private Optional readBlacklist(Connection conn, int boardId) {
stream(blChips.call(chip("x", "y"), boardId)).toSet();
var blacklistedCores =
stream(blCores.call(core("x", "y", "p"), boardId))
- .toCollectingMap(
- HashSet::new, c -> c.asChipLocation(),
- c -> c.getP());
- var blacklistedLinks =
- stream(blLinks.call(DeadLink::new, boardId))
- .toCollectingMap(
- () -> noneOf(Direction.class), d -> d.location,
- d -> d.direction);
+ .toCollectingMap(HashSet::new,
+ CoreLocation::asChipLocation,
+ CoreLocation::getP);
+ var blacklistedLinks = stream(blLinks.call(DeadLink::new, boardId))
+ .toCollectingMap(() -> noneOf(Direction.class),
+ DeadLink::location, DeadLink::direction);
if (blacklistedChips.isEmpty() && blacklistedCores.isEmpty()
&& blacklistedLinks.isEmpty()) {
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/FirmwareLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/FirmwareLoader.java
index 0cb109b7b9..2931318a18 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/FirmwareLoader.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/FirmwareLoader.java
@@ -21,6 +21,7 @@
import static java.lang.System.currentTimeMillis;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.time.Instant.ofEpochSecond;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.io.IOUtils.buffer;
@@ -35,15 +36,16 @@
import static uk.ac.manchester.spinnaker.messages.model.FPGAMainRegisters.LEDO;
import static uk.ac.manchester.spinnaker.messages.model.FPGAMainRegisters.SCRM;
import static uk.ac.manchester.spinnaker.messages.model.FPGAMainRegisters.SLEN;
-import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly;
import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.Serial;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -51,14 +53,13 @@
import java.util.Properties;
import java.util.zip.CRC32;
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
+import jakarta.annotation.PostConstruct;
import uk.ac.manchester.spinnaker.alloc.model.Prototype;
import uk.ac.manchester.spinnaker.machine.MemoryLocation;
import uk.ac.manchester.spinnaker.machine.board.BMPBoard;
@@ -168,6 +169,7 @@ public FirmwareLoader(BMPTransceiverInterface txrx, BMPBoard board) {
/** Base class of exceptions thrown by the firmware loader. */
public abstract static class FirmwareLoaderException
extends RuntimeException {
+ @Serial
private static final long serialVersionUID = -7057612243855126410L;
FirmwareLoaderException(String msg) {
@@ -177,6 +179,7 @@ public abstract static class FirmwareLoaderException
/** An update of the firmware on a BMP failed. */
public static class UpdateFailedException extends FirmwareLoaderException {
+ @Serial
private static final long serialVersionUID = 7925582707336953554L;
/** The data read back from the BMP. */
@@ -184,13 +187,13 @@ public static class UpdateFailedException extends FirmwareLoaderException {
UpdateFailedException(ByteBuffer data) {
super("failed to update flash data correctly!");
- this.data = data.asReadOnlyBuffer();
- this.data.order(LITTLE_ENDIAN);
+ this.data = readOnly(data);
}
}
/** A CRC check failed. */
public static class CRCFailedException extends FirmwareLoaderException {
+ @Serial
private static final long serialVersionUID = -4111893327837084643L;
/** The CRC calculated by the BMP. */
@@ -204,6 +207,7 @@ public static class CRCFailedException extends FirmwareLoaderException {
/** A data chunk was too large for the firmware loader to handle. */
public static class TooLargeException extends FirmwareLoaderException {
+ @Serial
private static final long serialVersionUID = -9025065456329109710L;
TooLargeException(long size) {
@@ -221,8 +225,7 @@ private static class FlashDataSector {
final ByteBuffer buf;
FlashDataSector() {
- buf = ByteBuffer.allocate(DATA_SECTOR_LENGTH);
- buf.order(LITTLE_ENDIAN);
+ buf = alloc(DATA_SECTOR_LENGTH);
}
static FlashDataSector registers(int numItems, List data) {
@@ -274,7 +277,7 @@ private void bitfileHeader(int mtime, int crc, FPGA chip, int timestamp,
buf.putShort((short) (BITFILE_ENABLED_FLAG + chip.bits));
buf.putInt(timestamp);
buf.putInt(crc);
- buf.putInt(baseAddress.address);
+ buf.putInt(baseAddress.address());
buf.putInt(length);
buf.putInt(mtime);
@@ -298,14 +301,14 @@ private void bitfileName(String name) {
* just immediately, but also during BMP boot.
*
* @author Donal Fellows
+ * @param fpga
+ * Which FPGA's register to set
+ * @param address
+ * The location of the register to set in the FPGA address space
+ * @param value
+ * What value to set
*/
- public static class RegisterSet {
- private final FPGA fpga;
-
- private final MemoryLocation address;
-
- private final int value;
-
+ public record RegisterSet(FPGA fpga, MemoryLocation address, int value) {
/**
* @param fpga
* Which FPGA's registers to set
@@ -315,9 +318,7 @@ public static class RegisterSet {
* The value to set
*/
public RegisterSet(FPGA fpga, FPGAMainRegisters register, int value) {
- this.fpga = fpga;
- this.address = register.getAddress();
- this.value = value;
+ this(fpga, register.getAddress(), value);
}
/**
@@ -332,9 +333,7 @@ public RegisterSet(FPGA fpga, FPGAMainRegisters register, int value) {
*/
public RegisterSet(FPGA fpga, FPGALinkRegisters register, int bank,
int value) {
- this.fpga = fpga;
- this.address = register.address(bank);
- this.value = value;
+ this(fpga, register.address(bank), value);
}
}
@@ -359,7 +358,7 @@ private ByteBuffer readFlashDataHead()
private static int crc(ByteBuffer buffer, int from, int len) {
var crc = new CRC32();
- crc.update(slice(buffer, from, len));
+ crc.update(buffer.slice(from, len));
return (int) (crc.getValue() & CRC_MASK);
}
@@ -401,8 +400,7 @@ private void logBMPVersion()
log.info("BMP INFO: {}",
format("%s %s at %s:%s (built %s) [C=%s, F=%s, B=%s]",
info.name, info.versionNumber, info.hardware,
- info.physicalCPUID,
- Instant.ofEpochSecond(info.buildDate),
+ info.physicalCPUID, ofEpochSecond(info.buildDate),
info.location.getCabinet(), info.location.getFrame(),
info.location.getBoard()));
}
@@ -417,19 +415,13 @@ private void listFPGABootChunks()
throws ProcessException, IOException, InterruptedException {
var data = readFlashDataHead();
for (int i = 0; i < NUM_DATA_SECTORS; i++) {
- var chunk = slice(data, DATA_SECTOR_CHUNK_SIZE * i,
- DATA_SECTOR_CHUNK_SIZE);
+ var chunk = data.slice(DATA_SECTOR_CHUNK_SIZE * i,
+ DATA_SECTOR_CHUNK_SIZE).order(LITTLE_ENDIAN);
byte type = chunk.get();
switch (DataSectorTypes.get(type)) {
- case REGISTER:
- logRegisterSets(chunk);
- break;
- case BITFILE:
- logFPGABootBitfile(chunk, i);
- break;
- default:
- // Ignore the chunk
- break;
+ case REGISTER -> logRegisterSets(chunk);
+ case BITFILE -> logFPGABootBitfile(chunk, i);
+ default -> log.trace("ignoring chunk with type code {}", type);
}
}
}
@@ -483,10 +475,8 @@ private void logFPGABootBitfile(ByteBuffer data, int i) {
length, crc));
log.info("FPGA BOOT: File {}",
new String(filenameBytes, 0, size, UTF_8).strip());
- log.info("FPGA BOOT: Written {}",
- Instant.ofEpochSecond(time));
- log.info("FPGA BOOT: ModTime {}",
- Instant.ofEpochSecond(mtime));
+ log.info("FPGA BOOT: Written {}", ofEpochSecond(time));
+ log.info("FPGA BOOT: ModTime {}", ofEpochSecond(mtime));
}
/**
@@ -508,8 +498,8 @@ public void setupRegisters(RegisterSet... settings)
throws ProcessException, IOException, InterruptedException {
var data = new ArrayList();
for (var r : settings) {
- data.add(r.address.address | r.fpga.value);
- data.add(r.value);
+ data.add(r.address().address() | r.fpga().value);
+ data.add(r.value());
}
var sector = FlashDataSector.registers(settings.length, data);
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/Link.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/Link.java
index 5591fb5b9a..cc24088bb1 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/Link.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/Link.java
@@ -23,14 +23,12 @@
* inter-board link to be off.
*
* @author Donal Fellows
+ * @param board
+ * The database ID of the board that the FPGA is located on.
+ * @param link
+ * Which link (and hence which FPGA).
*/
-public final class Link {
- /** The database ID of the board that the FPGA is located on. */
- private final BMPBoard board;
-
- /** Which link (and hence which FPGA). */
- private final Direction link;
-
+public record Link(BMPBoard board, Direction link) {
/**
* Create a request.
*
@@ -40,22 +38,11 @@ public final class Link {
* Which link (and hence which FPGA).
*/
Link(int board, Direction link) {
- this.board = new BMPBoard(board);
- this.link = link;
+ this(new BMPBoard(board), link);
}
@Override
public String toString() {
return "Link(" + board + "," + link + ":OFF)";
}
-
- /** @return The database ID of the board that the FPGA is located on. */
- public BMPBoard getBoard() {
- return board;
- }
-
- /** @return Which link (and hence which FPGA). */
- public Direction getLink() {
- return link;
- }
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/PhysicalSerialMapping.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/PhysicalSerialMapping.java
index 8c0615368c..7adf9b4600 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/PhysicalSerialMapping.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/PhysicalSerialMapping.java
@@ -17,8 +17,8 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.function.Predicate.not;
-import static org.slf4j.LoggerFactory.getLogger;
import static org.apache.commons.io.IOUtils.buffer;
+import static org.slf4j.LoggerFactory.getLogger;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -26,13 +26,13 @@
import java.util.HashMap;
import java.util.Map;
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
+import jakarta.annotation.PostConstruct;
+
/**
* Holds the mapping between physical board IDs and BMP IDs. Physical board IDs
* were allocated by the manufacturer of the boards (Norcott) and are
@@ -42,6 +42,9 @@
*
* The original form of blacklists stores them according to their physical board
* ID because that's what is easily available during commissioning.
+ *
+ * This class does not need to use locking to guard its internal state; after
+ * the bean enters service, that state is never modified.
*
* @author Donal Fellows
*/
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java
index 1ea2982f97..632cb0a0ad 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java
@@ -24,13 +24,12 @@
import java.util.List;
import java.util.Map;
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import jakarta.annotation.PostConstruct;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.TxrxProperties;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Machine;
import uk.ac.manchester.spinnaker.alloc.bmp.FirmwareLoader.FirmwareLoaderException;
@@ -148,7 +147,7 @@ void initTransceiver()
}
/** Notes that a board probably needs its FPGA definitions reloading. */
- private static class FPGAReloadRequired extends Exception {
+ private static final class FPGAReloadRequired extends Exception {
private static final long serialVersionUID = 1L;
final BMPBoard board;
@@ -210,7 +209,7 @@ private boolean isGoodFPGA(BMPBoard board, FPGA fpga)
private boolean canBoardManageFPGAs(BMPBoard board)
throws ProcessException, IOException, InterruptedException {
var vi = txrx.readBMPVersion(board);
- return vi.versionNumber.majorVersion >= BMP_VERSION_MIN;
+ return vi.versionNumber.majorVersion() >= BMP_VERSION_MIN;
}
/**
@@ -222,8 +221,8 @@ private boolean canBoardManageFPGAs(BMPBoard board)
@Override
public void setLinkOff(Link link)
throws ProcessException, IOException, InterruptedException {
- var board = link.getBoard();
- var d = link.getLink();
+ var board = link.board();
+ var d = link.link();
// skip FPGA link configuration if old BMP version
if (!canBoardManageFPGAs(board)) {
return;
@@ -258,7 +257,7 @@ private boolean hasGoodFPGAs(BMPBoard board)
public void powerOnAndCheck(List boards)
throws ProcessException, InterruptedException, IOException {
var boardsToPower = boards;
- log.debug("Power on and check boards {} for BMP {}", boards, bmp);
+ log.info("Power on and check boards {} for BMP {}", boards, bmp);
boolean reloadDone = false; // so we only do firmware loading once
for (int attempt = 1; attempt <= props.getFpgaAttempts(); attempt++) {
if (attempt > 1) {
@@ -317,24 +316,28 @@ public void powerOnAndCheck(List boards)
@Override
public void powerOff(List boards)
throws ProcessException, InterruptedException, IOException {
+ log.info("Power off boards {} for BMP {}", boards, bmp);
txrx.powerOff(boards);
}
@Override
public String readSerial(BMPBoard board)
throws ProcessException, IOException, InterruptedException {
+ log.info("Read serial number from board {} for BMP {}", board, bmp);
return txrx.readBoardSerialNumber(board);
}
@Override
public Blacklist readBlacklist(BMPBoard board)
throws ProcessException, IOException, InterruptedException {
+ log.info("Read blacklist from board {} for BMP {}", board, bmp);
return txrx.readBlacklist(board);
}
@Override
public void writeBlacklist(BMPBoard board, Blacklist blacklist)
throws ProcessException, InterruptedException, IOException {
+ log.info("Write blacklist to board {} for BMP {}", board, bmp);
txrx.writeBlacklist(board, blacklist);
}
@@ -346,6 +349,7 @@ public ADCInfo readTemp(BMPBoard board)
@Override
public void ping(List boards) {
+ log.info("Ping boards {} for BMP {}", boards, bmp);
boards.parallelStream().forEach(id -> {
var address = boardAddresses.get(id);
if (Ping.ping(address) != 0) {
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/TransceiverFactory.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/TransceiverFactory.java
index 820db18ef2..46b52cd351 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/TransceiverFactory.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/TransceiverFactory.java
@@ -15,21 +15,18 @@
*/
package uk.ac.manchester.spinnaker.alloc.bmp;
-import static java.util.Objects.hash;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.messages.Constants.SCP_SCAMP_PORT;
import static uk.ac.manchester.spinnaker.utils.InetFactory.getByName;
import static uk.ac.manchester.spinnaker.utils.Ping.ping;
import java.io.IOException;
+import java.io.Serial;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -37,6 +34,8 @@
import com.google.errorprone.annotations.RestrictedApi;
import com.google.errorprone.annotations.concurrent.GuardedBy;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import uk.ac.manchester.spinnaker.alloc.ForTestingOnly;
import uk.ac.manchester.spinnaker.alloc.ServiceMasterControl;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.TxrxProperties;
@@ -68,29 +67,7 @@ public class TransceiverFactory
implements TransceiverFactoryAPI {
private static final Logger log = getLogger(TransceiverFactory.class);
- private static final class Key {
- final String machine;
-
- final BMPCoords bmp;
-
- Key(String machine, BMPCoords bmp) {
- this.machine = machine;
- this.bmp = bmp;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Key) {
- var other = (Key) o;
- return machine.equals(other.machine) && bmp.equals(other.bmp);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return hash(machine, bmp);
- }
+ private record Key(String machine, BMPCoords bmp) {
}
@GuardedBy("itself")
@@ -130,18 +107,19 @@ public BMPTransceiverInterface getTransciever(Machine machineDescription,
}
} catch (TransceiverFactoryException e) {
var t = e.getCause();
- if (t instanceof IOException) {
- throw (IOException) t;
- } else if (t instanceof SpinnmanException) {
- throw (SpinnmanException) t;
- } else if (t instanceof InterruptedException) {
- throw (InterruptedException) t;
+ if (t instanceof IOException ioe) {
+ throw ioe;
+ } else if (t instanceof SpinnmanException se) {
+ throw se;
+ } else if (t instanceof InterruptedException ie) {
+ throw ie;
}
throw e;
}
}
private static class TransceiverFactoryException extends RuntimeException {
+ @Serial
private static final long serialVersionUID = 2102592240724419836L;
TransceiverFactoryException(String msg, Exception e) {
@@ -213,7 +191,7 @@ private Transceiver makeTransceiver(BMPConnectionData data)
throw e;
}
log.error("failed to connect to BMP; will ping and retry", e);
- log.debug("ping result was {}", ping(data.ipAddress));
+ log.debug("ping result was {}", ping(data.ipAddress()));
}
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Command.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Command.java
index 99f82a99db..5c28100cf6 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Command.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Command.java
@@ -22,12 +22,12 @@
import java.util.List;
import java.util.Map;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
/**
* The encoded form of a command to the server. This is basically a Python
* call encoded (except that no argument is a live object).
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ExceptionResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ExceptionResponse.java
index c4da80d07b..52d6a85ccc 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ExceptionResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ExceptionResponse.java
@@ -15,31 +15,12 @@
*/
package uk.ac.manchester.spinnaker.alloc.compat;
-import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
-import static java.util.Objects.isNull;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
/**
* A message indicating an operation failed.
*
* @author Donal Fellows
+ * @param exception
+ * The exception message.
*/
-@JsonAutoDetect(setterVisibility = NON_PRIVATE)
-final class ExceptionResponse {
- private String exception;
-
- ExceptionResponse(String message) {
- exception = message;
- }
-
- @JsonProperty("exception")
- public String getException() {
- return exception;
- }
-
- void setException(String exception) {
- this.exception = isNull(exception) ? "" : exception.toString();
- }
+record ExceptionResponse(String exception) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/JobNotifyMessage.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/JobNotifyMessage.java
index 73fca63f50..fe05ed2a3f 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/JobNotifyMessage.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/JobNotifyMessage.java
@@ -15,35 +15,17 @@
*/
package uk.ac.manchester.spinnaker.alloc.compat;
-import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
-
import java.util.List;
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A job notification message.
*
* @author Donal Fellows
+ * @param jobsChanged
+ * What jobs have had their state change
*/
-@JsonAutoDetect(setterVisibility = NON_PRIVATE)
-final class JobNotifyMessage {
- private List jobsChanged;
-
- JobNotifyMessage(List changes) {
- jobsChanged = changes;
- }
-
- /**
- * @return the jobs changed
- */
- @JsonProperty("jobs_changed")
- public List getJobsChanged() {
- return jobsChanged;
- }
-
- void setJobsChanged(List jobsChanged) {
- this.jobsChanged = jobsChanged;
- }
+record JobNotifyMessage(
+ @JsonProperty("jobs_changed") List jobsChanged) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/MachineNotifyMessage.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/MachineNotifyMessage.java
index c17b959635..5f063ca5a0 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/MachineNotifyMessage.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/MachineNotifyMessage.java
@@ -15,35 +15,17 @@
*/
package uk.ac.manchester.spinnaker.alloc.compat;
-import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
-
import java.util.List;
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A machine notification message.
*
* @author Donal Fellows
+ * @param machinesChanged
+ * What machines have had allocations on them change.
*/
-@JsonAutoDetect(setterVisibility = NON_PRIVATE)
-final class MachineNotifyMessage {
- private List machinesChanged;
-
- MachineNotifyMessage(List changes) {
- machinesChanged = changes;
- }
-
- /**
- * @return the machines changed
- */
- @JsonProperty("machines_changed")
- public List getMachinesChanged() {
- return machinesChanged;
- }
-
- void setMachinesChanged(List machinesChanged) {
- this.machinesChanged = machinesChanged;
- }
+record MachineNotifyMessage(
+ @JsonProperty("machines_changed") List machinesChanged) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ReturnResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ReturnResponse.java
index 3149929098..2ad1c20731 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ReturnResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/ReturnResponse.java
@@ -15,30 +15,14 @@
*/
package uk.ac.manchester.spinnaker.alloc.compat;
-import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A message indicating an operation succeeded.
*
* @author Donal Fellows
+ * @param returnValue
+ * The returned value
*/
-@JsonAutoDetect(setterVisibility = NON_PRIVATE)
-final class ReturnResponse {
- private Object returnValue;
-
- ReturnResponse(Object value) {
- returnValue = value;
- }
-
- @JsonProperty("return")
- public Object getReturnValue() {
- return returnValue;
- }
-
- void setReturnValue(Object returnValue) {
- this.returnValue = returnValue;
- }
+record ReturnResponse(@JsonProperty("return") Object returnValue) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/SaneParameter.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/SaneParameter.java
index c8c773c748..f1da204af5 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/SaneParameter.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/SaneParameter.java
@@ -25,10 +25,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
-import javax.validation.Constraint;
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-import javax.validation.Payload;
+import jakarta.validation.Constraint;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import jakarta.validation.Payload;
/**
* Validates that an argument is a sane value to pass in a classic spalloc API
@@ -69,8 +69,8 @@
class IsSaneValidator implements ConstraintValidator {
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
- if (value instanceof String) {
- return !((String) value).isBlank();
+ if (value instanceof String s) {
+ return !s.isBlank();
} else {
return (value instanceof Boolean) || (value instanceof Number);
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.java
index c84d51c056..0c6129e8f8 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.java
@@ -112,10 +112,10 @@ static Integer parseDec(Object value) {
int n;
if (isNull(value)) {
return null;
- } else if (value instanceof Number) {
- n = ((Number) value).intValue();
- } else if (value instanceof String) {
- n = parseInt((String) value);
+ } else if (value instanceof Number num) {
+ n = num.intValue();
+ } else if (value instanceof String s) {
+ n = parseInt(s);
} else {
throw new IllegalArgumentException(
"needed a number, got a " + value.getClass().getName());
@@ -222,18 +222,14 @@ static Double timestamp(Instant instant) {
* @return The converted state.
*/
static State state(JobState state) {
- switch (state) {
- case QUEUED:
- return State.QUEUED;
- case POWER:
- return State.POWER;
- case READY:
- return State.READY;
- case DESTROYED:
- return State.DESTROYED;
- default:
- return State.UNKNOWN;
- }
+ // So trivial...
+ return switch (state) {
+ case QUEUED -> State.QUEUED;
+ case POWER -> State.POWER;
+ case READY -> State.READY;
+ case DESTROYED -> State.DESTROYED;
+ default -> State.UNKNOWN;
+ };
}
/**
@@ -244,8 +240,7 @@ static State state(JobState state) {
* @return The converted coordinate.
*/
static BoardCoordinates board(BoardCoords coords) {
- return new BoardCoordinates(coords.getX(), coords.getY(),
- coords.getZ());
+ return new BoardCoordinates(coords.x(), coords.y(), coords.z());
}
/**
@@ -256,13 +251,13 @@ static BoardCoordinates board(BoardCoords coords) {
* @return A stream of ends of the link.
*/
static Stream boardLinks(DownLink downLink) {
- var bl1 = new BoardLink(downLink.end1.board.getX(),
- downLink.end1.board.getY(), downLink.end1.board.getZ(),
- downLink.end1.direction.ordinal());
+ var bl1 = new BoardLink(downLink.end1().board().x(),
+ downLink.end1().board().y(), downLink.end1().board().z(),
+ downLink.end1().direction().ordinal());
- var bl2 = new BoardLink(downLink.end2.board.getX(),
- downLink.end2.board.getY(), downLink.end2.board.getZ(),
- downLink.end2.direction.ordinal());
+ var bl2 = new BoardLink(downLink.end2().board().x(),
+ downLink.end2().board().y(), downLink.end2().board().z(),
+ downLink.end2().direction().ordinal());
return List.of(bl1, bl2).stream();
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatService.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatService.java
index 467ab7f17e..1c9e6d5b7c 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatService.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatService.java
@@ -36,9 +36,6 @@
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,8 +43,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.errorprone.annotations.RestrictedApi;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import uk.ac.manchester.spinnaker.alloc.ForTestingOnly;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.CompatibilityProperties;
@@ -100,7 +101,8 @@ public class V1CompatService {
V1CompatService() {
mapper = JsonMapper.builder().propertyNamingStrategy(SNAKE_CASE)
- .build();
+ .addModule(new Jdk8Module())
+ .addModule(new JavaTimeModule()).build();
var group = new ThreadGroup("spalloc-legacy-service");
var counter = new ValueHolder<>(1);
threadFactory = r -> {
@@ -227,7 +229,7 @@ private void acceptConnections() {
private boolean acceptConnection() {
try {
var service = getTask(serv.accept());
- executor.execute(() -> service.handleConnection());
+ executor.execute(service::handleConnection);
} catch (SocketException e) {
// Check here; interrupt = shutting down = no errors, please
if (interrupted()) {
@@ -287,7 +289,7 @@ public Future> launchInstance(PipedWriter in, PipedReader out)
throws Exception {
var service = taskFactory.getObject(V1CompatService.this,
new PipedReader(in), new PipedWriter(out));
- return executor.submit(() -> service.handleConnection());
+ return executor.submit(service::handleConnection);
}
};
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTask.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTask.java
index fd9d81f993..e67cf57a06 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTask.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTask.java
@@ -43,11 +43,6 @@
import java.util.Objects;
import java.util.Optional;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-
import org.slf4j.Logger;
import com.fasterxml.jackson.core.JsonParseException;
@@ -55,6 +50,10 @@
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.google.errorprone.annotations.concurrent.GuardedBy;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import uk.ac.manchester.spinnaker.alloc.model.PowerState;
import uk.ac.manchester.spinnaker.machine.ValidP;
import uk.ac.manchester.spinnaker.machine.ValidX;
@@ -162,23 +161,31 @@ final void handleConnection() {
} catch (InterruptedException | InterruptedIOException interrupted) {
log.debug("interrupted", interrupted);
} catch (IOException e) {
- log.error("problem with socket {}", sock, e);
+ if (!e.getMessage().equals("Pipe closed")) {
+ log.error("problem with socket {}", sock, e);
+ }
} finally {
- log.debug("closing down connection from {}", sock);
- closeNotifiers();
- try {
- if (nonNull(sock)) {
- sock.close();
- } else {
- in.close();
- synchronized (out) {
- out.close();
- }
+ shutdown();
+ }
+ }
+
+ private void shutdown() {
+ var origin = nonNull(sock) ? sock : "TEST";
+ log.debug("closing down connection from {}", origin);
+ closeNotifiers();
+ try {
+ if (nonNull(sock)) {
+ sock.close();
+ } else {
+ in.close();
+ synchronized (out) {
+ out.close();
}
- } catch (IOException e) {
- log.error("problem closing socket {}", sock, e);
}
+ } catch (IOException e) {
+ log.error("problem closing connection {}", origin, e);
}
+ log.debug("closed connection from {}", origin);
}
/**
@@ -258,13 +265,18 @@ private Optional readMessage()
* than matching the exception message. You'd think that you'd get
* something better, but no...
*/
- switch (e.getMessage()) {
- case "Connection reset":
- case "Connection timed out (Read failed)":
- return Optional.empty();
- default:
- throw e;
- }
+ return switch (e.getMessage()) {
+ case "Connection reset", "Connection timed out (Read failed)" ->
+ Optional.empty();
+ default -> throw e;
+ };
+ } catch (InterruptedIOException e) {
+ var ex = new InterruptedException();
+ ex.initCause(e);
+ throw ex;
+ }
+ if (currentThread().isInterrupted()) {
+ throw new InterruptedException();
}
if (currentThread().isInterrupted()) {
throw new InterruptedException();
@@ -438,73 +450,76 @@ private Object callOperation(Command cmd) throws Exception {
log.debug("calling operation '{}'", cmd.getCommand());
var args = cmd.getArgs();
var kwargs = cmd.getKwargs();
- switch (cmd.getCommand()) {
- case "create_job":
+ return switch (cmd.getCommand()) {
+ case "create_job" -> {
// This is three operations really, and an optional parameter.
byte[] serialCmd = getJsonMapper().writeValueAsBytes(cmd);
- switch (args.size()) {
- case 0:
- return createJobNumBoards(1, kwargs, serialCmd).orElse(null);
- case 1:
- return createJobNumBoards(parseDec(args, 0), kwargs, serialCmd)
- .orElse(null);
- case 2:
- return createJobRectangle(parseDec(args, 0), parseDec(args, 1),
- kwargs, serialCmd).orElse(null);
- case TRIAD_COORD_COUNT:
- return createJobSpecificBoard(new TriadCoords(parseDec(args, 0),
+ // Checkstyle bug: indentation confusion
+ // CHECKSTYLE:OFF
+ yield switch (args.size()) {
+ case 0 -> createJobNumBoards(1, kwargs, serialCmd).orElse(null);
+ case 1 -> createJobNumBoards(parseDec(args, 0), kwargs, serialCmd)
+ .orElse(null);
+ case 2 -> createJobRectangle(parseDec(args, 0), parseDec(args, 1),
+ kwargs, serialCmd).orElse(null);
+ case TRIAD_COORD_COUNT ->
+ createJobSpecificBoard(new TriadCoords(parseDec(args, 0),
parseDec(args, 1), parseDec(args, 2)), kwargs,
serialCmd).orElse(null);
- default:
- throw new Oops(
- "unsupported number of arguments: " + args.size());
- }
- case "destroy_job":
+ default -> throw new Oops(
+ "unsupported number of arguments: " + args.size());
+ };
+ // CHECKSTYLE:ON
+ }
+ case "destroy_job" -> {
destroyJob(parseDec(args, 0), (String) kwargs.get("reason"));
- break;
- case "get_board_at_position":
- return requireNonNull(getBoardAtPhysicalPosition(
- (String) kwargs.get("machine_name"), parseDec(kwargs, "x"),
- parseDec(kwargs, "y"), parseDec(kwargs, "z")));
- case "get_board_position":
- return requireNonNull(getBoardAtLogicalPosition(
+ yield null;
+ }
+ case "get_board_at_position" ->
+ requireNonNull(getBoardAtPhysicalPosition(
(String) kwargs.get("machine_name"), parseDec(kwargs, "x"),
parseDec(kwargs, "y"), parseDec(kwargs, "z")));
- case "get_job_machine_info":
- return requireNonNull(getJobMachineInfo(parseDec(args, 0)));
- case "get_job_state":
- return requireNonNull(getJobState(parseDec(args, 0)));
- case "job_keepalive":
+ case "get_board_position" -> requireNonNull(getBoardAtLogicalPosition(
+ (String) kwargs.get("machine_name"), parseDec(kwargs, "x"),
+ parseDec(kwargs, "y"), parseDec(kwargs, "z")));
+ case "get_job_machine_info" ->
+ requireNonNull(getJobMachineInfo(parseDec(args, 0)));
+ case "get_job_state" -> requireNonNull(getJobState(parseDec(args, 0)));
+ case "job_keepalive" -> {
jobKeepalive(parseDec(args, 0));
- break;
- case "list_jobs":
- return requireNonNull(listJobs());
- case "list_machines":
- return requireNonNull(listMachines());
- case "no_notify_job":
+ yield null;
+ }
+ case "list_jobs" -> requireNonNull(listJobs());
+ case "list_machines" -> requireNonNull(listMachines());
+ case "no_notify_job" -> {
notifyJob(optInt(args), false);
- break;
- case "no_notify_machine":
+ yield null;
+ }
+ case "no_notify_machine" -> {
notifyMachine(optStr(args), false);
- break;
- case "notify_job":
+ yield null;
+ }
+ case "notify_job" -> {
notifyJob(optInt(args), true);
- break;
- case "notify_machine":
+ yield null;
+ }
+ case "notify_machine" -> {
notifyMachine(optStr(args), true);
- break;
- case "power_off_job_boards":
+ yield null;
+ }
+ case "power_off_job_boards" -> {
powerJobBoards(parseDec(args, 0), OFF);
- break;
- case "power_on_job_boards":
+ yield null;
+ }
+ case "power_on_job_boards" -> {
powerJobBoards(parseDec(args, 0), ON);
- break;
- case "version":
- return requireNonNull(version());
- case "where_is":
+ yield null;
+ }
+ case "version" -> requireNonNull(version());
+ case "where_is" -> {
// This is four operations in a trench coat
if (kwargs.containsKey("job_id")) {
- return requireNonNull(whereIsJobChip(parseDec(kwargs, "job_id"),
+ yield requireNonNull(whereIsJobChip(parseDec(kwargs, "job_id"),
parseDec(kwargs, "chip_x"),
parseDec(kwargs, "chip_y")));
} else if (!kwargs.containsKey("machine")) {
@@ -512,21 +527,22 @@ private Object callOperation(Command cmd) throws Exception {
}
var m = (String) kwargs.get("machine");
if (kwargs.containsKey("chip_x")) {
- return requireNonNull(
+ yield requireNonNull(
whereIsMachineChip(m, parseDec(kwargs, "chip_x"),
parseDec(kwargs, "chip_y")));
} else if (kwargs.containsKey("x")) {
- return requireNonNull(
+ yield requireNonNull(
whereIsMachineLogicalBoard(m, parseDec(kwargs, "x"),
parseDec(kwargs, "y"), parseDec(kwargs, "z")));
} else if (kwargs.containsKey("cabinet")) {
- return requireNonNull(whereIsMachinePhysicalBoard(m,
+ yield requireNonNull(whereIsMachinePhysicalBoard(m,
parseDec(kwargs, "cabinet"), parseDec(kwargs, "frame"),
parseDec(kwargs, "board")));
} else {
throw new Oops("missing parameter: chip_x, x, or cabinet");
}
- case "report_problem":
+ }
+ case "report_problem" -> {
var ip = args.get(0).toString();
Integer x = null, y = null, p = null;
var desc = "It doesn't work and I don't know why.";
@@ -541,13 +557,11 @@ private Object callOperation(Command cmd) throws Exception {
desc = Objects.toString(kwargs.get("description"));
}
reportProblem(ip, x, y, p, desc);
- break;
- case "login":
- throw new Oops("upgrading security is not supported");
- default:
- throw new Oops("unknown command: " + cmd.getCommand());
+ yield null;
}
- return null;
+ case "login" -> throw new Oops("upgrading security is not supported");
+ default -> throw new Oops("unknown command: " + cmd.getCommand());
+ };
}
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java
index bb2cdd557b..fe6b87d525 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java
@@ -47,13 +47,12 @@
import java.util.Optional;
import java.util.concurrent.Future;
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
+import jakarta.annotation.PostConstruct;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
import uk.ac.manchester.spinnaker.alloc.allocator.Epochs;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI;
@@ -92,7 +91,6 @@
@Component
@Prototype
class V1TaskImpl extends V1CompatTask {
-
/**
* We are compatible with spalloc-server release version 5.0.0.
*/
@@ -185,7 +183,7 @@ protected final JobMachineInfo getJobMachineInfo(int jobId)
}
}
return new JobMachineInfo(w, h, machine.getConnections().stream()
- .map(ci -> new Connection(ci.getChip(), ci.getHostname()))
+ .map(ci -> new Connection(ci.chip(), ci.hostname()))
.collect(toList()), machine.getMachine().getName(),
machine.getBoards());
}
@@ -246,12 +244,12 @@ private Duration parseKeepalive(Number keepalive) {
*/
private static List tags(Object src, boolean mayForceDefault) {
var vals = new ArrayList();
- if (src instanceof List) {
- for (var o : (List>) src) {
+ if (src instanceof List> lst) {
+ for (var o : lst) {
vals.add(Objects.toString(o));
}
- } else if (src instanceof String) {
- vals.add((String) src);
+ } else if (src instanceof String s) {
+ vals.add(s);
}
if (vals.isEmpty() && mayForceDefault) {
return List.of("default");
@@ -277,7 +275,8 @@ protected final Optional createJobRectangle(int width, int height,
@Override
protected final Optional createJobSpecificBoard(TriadCoords coords,
Map kwargs, byte[] cmd) throws TaskException {
- return createJob(triad(coords.x, coords.y, coords.z), kwargs, cmd);
+ return createJob(triad(coords.x(), coords.y(), coords.z()), kwargs,
+ cmd);
}
private static String getOwner(Map kwargs)
@@ -370,7 +369,7 @@ private static JobDescription buildJobDescription(V1TaskImpl task,
jd.setArgs(args);
jd.setKwargs(cmd.getKwargs());
// Override shrouded owner from above
- Object owner = cmd.getKwargs().get("owner");
+ var owner = cmd.getKwargs().get("owner");
if (owner != null) {
jd.setOwner(owner.toString());
}
@@ -378,7 +377,7 @@ private static JobDescription buildJobDescription(V1TaskImpl task,
jd.setMachine(job.getMachineName());
jd.setPower(job.isPowered());
jd.setBoards(job.getBoards().stream().map(
- b -> new BoardCoordinates(b.getX(), b.getY(), b.getZ()))
+ b -> new BoardCoordinates(b.x(), b.y(), b.z()))
.collect(toList()));
return jd.build();
}
@@ -470,7 +469,7 @@ protected final void notifyMachine(String machineName, boolean wantNotify)
try {
var changed = epoch.getChanged(
mainProps.getCompat().getNotifyWaitTime());
- return changed.stream().map(id -> invMap.get(id))
+ return changed.stream().map(invMap::get)
.collect(toList());
} catch (InterruptedException e) {
return List.of();
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DataAccessExceptionMapper.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DataAccessExceptionMapper.java
index d471a8a6e0..c8fd149799 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DataAccessExceptionMapper.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DataAccessExceptionMapper.java
@@ -15,21 +15,20 @@
*/
package uk.ac.manchester.spinnaker.alloc.db;
-import static javax.ws.rs.core.Response.status;
-import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static jakarta.ws.rs.core.Response.status;
+import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Role;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngineJDBCImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngineJDBCImpl.java
index 562fb53c0d..3a58f0c309 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngineJDBCImpl.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngineJDBCImpl.java
@@ -32,8 +32,6 @@
import java.util.List;
import java.util.Optional;
-import javax.annotation.PostConstruct;
-
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -51,6 +49,8 @@
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
+import jakarta.annotation.PostConstruct;
+
/**
* Implementation of the {@link DatabaseAPI} that uses JDBC to talk to MySQL.
*/
@@ -256,16 +256,16 @@ final Object[] resolveArguments(Object[] arguments) {
for (int i = 0; i < arguments.length; i++) {
var arg = arguments[i];
// The classes we augment the DB driver with
- if (arg instanceof Optional) {
+ if (arg instanceof Optional> opt) {
// Unpack one layer of Optional only; absent = NULL
- arg = ((Optional>) arg).orElse(null);
+ arg = opt.orElse(null);
}
- if (arg instanceof Instant) {
- arg = ((Instant) arg).getEpochSecond();
- } else if (arg instanceof Duration) {
- arg = ((Duration) arg).getSeconds();
- } else if (arg instanceof Enum) {
- arg = ((Enum>) arg).ordinal();
+ if (arg instanceof Instant inst) {
+ arg = inst.getEpochSecond();
+ } else if (arg instanceof Duration d) {
+ arg = d.getSeconds();
+ } else if (arg instanceof Enum> e) {
+ arg = e.ordinal();
} else if (arg != null && arg instanceof Serializable
&& !(arg instanceof String || arg instanceof Number
|| arg instanceof Boolean
@@ -363,8 +363,7 @@ public Optional key(Object... arguments) {
*/
private String readSQL(Resource resource) {
try (var is = resource.getInputStream()) {
- var s = IOUtils.toString(is, UTF_8);
- return s;
+ return IOUtils.toString(is, UTF_8);
} catch (IOException e) {
throw new UncategorizedScriptException(
"could not load SQL file from " + resource, e);
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Row.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Row.java
index 28fd9b4e5a..40b885313c 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Row.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Row.java
@@ -211,11 +211,11 @@ public static ToIntFunction int32(String columnLabel) {
public Integer getInteger(String columnLabel) {
return get(() -> {
var obj = rs.getObject(columnLabel);
- if (obj instanceof Long) {
- return ((Long) obj).intValue();
+ if (obj instanceof Long l) {
+ return l.intValue();
}
- if (obj instanceof BigDecimal) {
- return ((BigDecimal) obj).intValue();
+ if (obj instanceof BigDecimal bd) {
+ return bd.intValue();
}
return (Integer) obj;
});
@@ -545,6 +545,6 @@ public static RowMapper core(String x, String y, String p) {
* @return A mappable iterator.
*/
public static MappableIterable stream(List lst) {
- return () -> lst.iterator();
+ return lst::iterator;
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLExceptionMapper.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLExceptionMapper.java
index 62982ecb5e..5e14ab06d2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLExceptionMapper.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLExceptionMapper.java
@@ -15,20 +15,19 @@
*/
package uk.ac.manchester.spinnaker.alloc.db;
-import static javax.ws.rs.core.Response.status;
-import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static jakarta.ws.rs.core.Response.status;
+import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import static org.slf4j.LoggerFactory.getLogger;
import java.sql.SQLException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLQueries.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLQueries.java
index 6dde35fa35..57e7c3ef40 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLQueries.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/SQLQueries.java
@@ -60,20 +60,22 @@ public abstract class SQLQueries {
@ResultColumn("width")
@ResultColumn("height")
@ResultColumn("in_service")
- protected static final String GET_ALL_MACHINES =
- "SELECT machine_id, machine_name, width, height, in_service "
- + "FROM machines "
- + "WHERE in_service OR :allow_out_of_service "
- + "ORDER BY machine_name ASC";
+ protected static final String GET_ALL_MACHINES = """
+ SELECT machine_id, machine_name, width, height, in_service
+ FROM machines
+ WHERE in_service OR :allow_out_of_service
+ ORDER BY machine_name ASC
+ """;
/** Get the machine names in alphabetical order. */
@Parameter("allow_out_of_service")
@ResultColumn("machine_name")
@ResultColumn("in_service")
- protected static final String LIST_MACHINE_NAMES =
- "SELECT machine_name, in_service FROM machines "
- + "WHERE in_service OR :allow_out_of_service "
- + "ORDER BY machine_name ASC";
+ protected static final String LIST_MACHINE_NAMES = """
+ SELECT machine_name, in_service FROM machines
+ WHERE in_service OR :allow_out_of_service
+ ORDER BY machine_name ASC
+ """;
/** Get basic information about a specific machine. Looks up by ID. */
@Parameter("machine_id")
@@ -84,10 +86,13 @@ public abstract class SQLQueries {
@ResultColumn("height")
@ResultColumn("in_service")
@SingleRowResult
- protected static final String GET_MACHINE_BY_ID =
- "SELECT machine_id, machine_name, width, height, in_service "
- + "FROM machines WHERE machine_id = :machine_id "
- + "AND (in_service OR :allow_out_of_service) LIMIT 1";
+ protected static final String GET_MACHINE_BY_ID = """
+ SELECT machine_id, machine_name, width, height, in_service
+ FROM machines
+ WHERE machine_id = :machine_id
+ AND (in_service OR :allow_out_of_service)
+ LIMIT 1
+ """;
/** Get basic information about a specific machine. Looks up by name. */
@Parameter("machine_name")
@@ -98,10 +103,13 @@ public abstract class SQLQueries {
@ResultColumn("height")
@ResultColumn("in_service")
@SingleRowResult
- protected static final String GET_NAMED_MACHINE =
- "SELECT machine_id, machine_name, width, height, in_service "
- + "FROM machines WHERE machine_name = :machine_name "
- + "AND (in_service OR :allow_out_of_service) LIMIT 1";
+ protected static final String GET_NAMED_MACHINE = """
+ SELECT machine_id, machine_name, width, height, in_service
+ FROM machines
+ WHERE machine_name = :machine_name
+ AND (in_service OR :allow_out_of_service)
+ LIMIT 1
+ """;
/**
* Get whether a machine wraps in horizontal or vertical directions.
@@ -111,24 +119,30 @@ public abstract class SQLQueries {
@ResultColumn("horizontal_wrap")
@ResultColumn("vertical_wrap")
@SingleRowResult
- protected static final String GET_MACHINE_WRAPS =
- "WITH linked AS ("
- + "SELECT b1.machine_id, b1.x AS x1, b1.y AS y1, "
- + "b2.x AS x2, b2.y AS y2 FROM links "
- + "JOIN boards AS b1 ON links.board_1 = b1.board_id "
- + "JOIN boards AS b2 ON links.board_2 = b2.board_id) "
- + "SELECT "
- + "EXISTS (SELECT 1 FROM linked WHERE "
- + "linked.machine_id = machines.machine_id AND "
- + "((linked.x1 = 0 AND linked.x2 = machines.width - 1) OR "
- + "(linked.x2 = 0 AND linked.x1 = machines.width - 1))) "
- + "AS horizontal_wrap, "
- + "EXISTS (SELECT 1 FROM linked WHERE "
- + "linked.machine_id = machines.machine_id AND "
- + "((linked.y1 = 0 AND linked.y2 = machines.height - 1) OR "
- + "(linked.y2 = 0 AND linked.y1 = machines.height - 1))) "
- + "AS vertical_wrap "
- + "FROM machines WHERE machine_id = :machine_id LIMIT 1";
+ protected static final String GET_MACHINE_WRAPS = """
+ WITH linked AS (
+ SELECT b1.machine_id, b1.x AS x1, b1.y AS y1,
+ b2.x AS x2, b2.y AS y2
+ FROM links
+ JOIN boards AS b1 ON links.board_1 = b1.board_id
+ JOIN boards AS b2 ON links.board_2 = b2.board_id)
+ SELECT
+ EXISTS (
+ SELECT 1 FROM linked
+ WHERE linked.machine_id = machines.machine_id
+ AND ((linked.x1 = 0 AND linked.x2 = machines.width - 1)
+ OR (linked.x2 = 0 AND linked.x1 = machines.width - 1))
+ ) AS horizontal_wrap,
+ EXISTS (
+ SELECT 1 FROM linked
+ WHERE linked.machine_id = machines.machine_id
+ AND ((linked.y1 = 0 AND linked.y2 = machines.height - 1)
+ OR (linked.y2 = 0 AND linked.y1 = machines.height - 1))
+ ) AS vertical_wrap
+ FROM machines
+ WHERE machine_id = :machine_id
+ LIMIT 1
+ """;
/** Count things on a machine. */
@Parameter("machine_id")
@@ -136,16 +150,18 @@ public abstract class SQLQueries {
@ResultColumn("in_use")
@ResultColumn("num_jobs")
@SingleRowResult
- protected static final String COUNT_MACHINE_THINGS =
- "WITH args(m) AS (SELECT :machine_id), "
- + "b AS (SELECT * from boards,args WHERE machine_id = m), "
- + "bc AS (SELECT COUNT(*) AS c FROM b), "
- + "iu AS (SELECT COUNT(*) AS c FROM b "
- + "WHERE allocated_job IS NOT NULL), "
- + "jc AS (SELECT COUNT(*) AS c FROM jobs,args "
- + "WHERE machine_id = m AND job_state != 4) " // DESTROYED
- + "SELECT bc.c AS board_count, iu.c AS in_use, "
- + "jc.c AS num_jobs FROM bc, iu, jc";
+ protected static final String COUNT_MACHINE_THINGS = """
+ WITH args(m) AS (SELECT :machine_id),
+ b AS (SELECT * from boards, args WHERE machine_id = m),
+ bc AS (SELECT COUNT(*) AS c FROM b),
+ iu AS (SELECT COUNT(*) AS c FROM b
+ WHERE allocated_job IS NOT NULL),
+ jc AS (SELECT COUNT(*) AS c FROM jobs,args
+ WHERE machine_id = m
+ AND job_state != 4) -- job is not DESTROYED
+ SELECT bc.c AS board_count, iu.c AS in_use,
+ jc.c AS num_jobs FROM bc, iu, jc
+ """;
/** Get basic information about jobs. Supports paging. */
@Parameter("limit")
@@ -154,10 +170,12 @@ public abstract class SQLQueries {
@ResultColumn("machine_id")
@ResultColumn("job_state")
@ResultColumn("keepalive_timestamp")
- protected static final String GET_JOB_IDS =
- "SELECT job_id, machine_id, job_state, keepalive_timestamp "
- + "FROM jobs ORDER BY job_id DESC "
- + "LIMIT :limit OFFSET :offset";
+ protected static final String GET_JOB_IDS = """
+ SELECT job_id, machine_id, job_state, keepalive_timestamp
+ FROM jobs
+ ORDER BY job_id DESC
+ LIMIT :limit OFFSET :offset
+ """;
/** Get basic information about live jobs. Supports paging. */
@Parameter("limit")
@@ -166,10 +184,13 @@ public abstract class SQLQueries {
@ResultColumn("machine_id")
@ResultColumn("job_state")
@ResultColumn("keepalive_timestamp")
- protected static final String GET_LIVE_JOB_IDS =
- "SELECT job_id, machine_id, job_state, keepalive_timestamp "
- + "FROM jobs WHERE job_state != 4 " // DESTROYED
- + "ORDER BY job_id DESC LIMIT :limit OFFSET :offset";
+ protected static final String GET_LIVE_JOB_IDS = """
+ SELECT job_id, machine_id, job_state, keepalive_timestamp
+ FROM jobs
+ WHERE job_state != 4 -- job is not DESTROYED
+ ORDER BY job_id DESC
+ LIMIT :limit OFFSET :offset
+ """;
/** Get basic information about a specific job. */
@Parameter("job_id")
@@ -190,40 +211,48 @@ public abstract class SQLQueries {
@ResultColumn("original_request")
@ResultColumn("owner")
@SingleRowResult
- protected static final String GET_JOB =
- "SELECT job_id, jobs.machine_id, machines.machine_name, "
- + "jobs.width, jobs.height, jobs.depth, "
- + "root_id, job_state, keepalive_timestamp, "
- + "keepalive_host, keepalive_interval, create_timestamp, "
- + "death_reason, death_timestamp, original_request, "
- + "user_info.user_name AS owner FROM jobs "
- + "JOIN user_info ON jobs.owner = user_info.user_id "
- + "JOIN machines USING (machine_id) "
- + "WHERE job_id = :job_id LIMIT 1";
+ protected static final String GET_JOB = """
+ SELECT job_id, jobs.machine_id, machines.machine_name,
+ jobs.width, jobs.height, jobs.depth,
+ root_id, job_state, keepalive_timestamp,
+ keepalive_host, keepalive_interval, create_timestamp,
+ death_reason, death_timestamp, original_request,
+ user_info.user_name AS owner
+ FROM jobs
+ JOIN user_info ON jobs.owner = user_info.user_id
+ JOIN machines USING (machine_id)
+ WHERE job_id = :job_id
+ LIMIT 1
+ """;
/** Get the chip dimensions of a job. */
@Parameter("job_id")
@ResultColumn("width")
@ResultColumn("height")
@SingleRowResult
- protected static final String GET_JOB_CHIP_DIMENSIONS =
- "WITH b AS (SELECT * FROM boards WHERE allocated_job = :job_id), "
- + "c AS (SELECT root_x + chip_x AS x, root_y + chip_y AS y "
- + "FROM b JOIN machines USING (machine_id) "
- + "JOIN board_model_coords ON "
- + "machines.board_model = board_model_coords.model) "
- + "SELECT MAX(x) - MIN(x) + 1 AS width, "
- + "MAX(y) - MIN(y) + 1 AS height FROM c LIMIT 1";
+ protected static final String GET_JOB_CHIP_DIMENSIONS = """
+ WITH b AS (SELECT * FROM boards WHERE allocated_job = :job_id),
+ c AS (SELECT root_x + chip_x AS x, root_y + chip_y AS y
+ FROM b JOIN machines USING (machine_id)
+ JOIN board_model_coords ON
+ machines.board_model = board_model_coords.model)
+ SELECT MAX(x) - MIN(x) + 1 AS width,
+ MAX(y) - MIN(y) + 1 AS height
+ FROM c
+ LIMIT 1
+ """;
/** Get what boards are allocated to a job. */
@Parameter("job_id")
@ResultColumn("board_id")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_JOB_BOARDS =
- "SELECT board_id, bmp_id, boards.machine_id FROM boards JOIN jobs "
- + "ON boards.allocated_job = jobs.job_id "
- + "WHERE boards.allocated_job = :job_id";
+ protected static final String GET_JOB_BOARDS = """
+ SELECT board_id, bmp_id, boards.machine_id
+ FROM boards
+ JOIN jobs ON boards.allocated_job = jobs.job_id
+ WHERE boards.allocated_job = :job_id
+ """;
/** Gets information about live jobs. */
@ResultColumn("job_id")
@@ -236,31 +265,38 @@ public abstract class SQLQueries {
@ResultColumn("user_name")
@ResultColumn("machine_name")
@ResultColumn("original_request")
- protected static final String LIST_LIVE_JOBS =
- "SELECT job_id, jobs.machine_id, create_timestamp, "
- + "keepalive_interval, job_state, allocation_size, "
- + "keepalive_host, user_name, machines.machine_name, "
- + "original_request "
- + "FROM jobs " + "JOIN machines USING (machine_id) "
- + "JOIN user_info ON jobs.owner = user_info.user_id "
- + "WHERE job_state != 4"; // DESTROYED
+ protected static final String LIST_LIVE_JOBS = """
+ SELECT job_id, jobs.machine_id, create_timestamp,
+ keepalive_interval, job_state, allocation_size,
+ keepalive_host, user_name, machines.machine_name,
+ original_request
+ FROM jobs
+ JOIN machines USING (machine_id)
+ JOIN user_info ON jobs.owner = user_info.user_id
+ WHERE job_state != 4 -- job is not DESTROYED
+ """;
/** Counts the number of powered-on boards of a job. */
@Parameter("job_id")
@ResultColumn("c")
@SingleRowResult
- protected static final String COUNT_POWERED_BOARDS =
- "SELECT COUNT(*) AS c FROM boards "
- + "WHERE allocated_job = :job_id AND board_power";
+ protected static final String COUNT_POWERED_BOARDS = """
+ SELECT COUNT(*) AS c
+ FROM boards
+ WHERE allocated_job = :job_id AND board_power
+ """;
/** Get the coordinates of the root chip of a board. */
@Parameter("board_id")
@ResultColumn("root_x")
@ResultColumn("root_y")
@SingleRowResult
- protected static final String GET_ROOT_OF_BOARD =
- "SELECT root_x, root_y FROM boards WHERE board_id = :board_id "
- + "LIMIT 1";
+ protected static final String GET_ROOT_OF_BOARD = """
+ SELECT root_x, root_y
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/** Create a job. */
@Parameter("machine_id")
@@ -269,13 +305,15 @@ public abstract class SQLQueries {
@Parameter("keepalive_interval")
@Parameter("original_request")
@GeneratesID
- protected static final String INSERT_JOB = "INSERT INTO jobs("
- + "machine_id, owner, group_id, keepalive_interval, "
- + "original_request, keepalive_timestamp, create_timestamp, "
- + "job_state) "
- + "VALUES(:machine_id, :user_id, :group_id, :keepalive_interval, "
- + ":original_request, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), "
- + /* QUEUED */ "1)";
+ protected static final String INSERT_JOB = """
+ INSERT INTO jobs(
+ machine_id, owner, group_id, keepalive_interval,
+ original_request, keepalive_timestamp, create_timestamp,
+ job_state)
+ VALUES(:machine_id, :user_id, :group_id, :keepalive_interval,
+ :original_request, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(),
+ 1) -- job starts QUEUED
+ """;
/** Create a request to allocate a number of boards. */
@Parameter("job_id")
@@ -283,11 +321,11 @@ public abstract class SQLQueries {
@Parameter("max_dead_boards")
@Parameter("priority")
@GeneratesID
- protected static final String INSERT_REQ_N_BOARDS =
- "INSERT INTO job_request(job_id, num_boards, max_dead_boards, "
- + "priority) "
- + "VALUES (:job_id, :num_boards, :max_dead_boards, "
- + ":priority)";
+ protected static final String INSERT_REQ_N_BOARDS = """
+ INSERT INTO job_request(
+ job_id, num_boards, max_dead_boards, priority)
+ VALUES (:job_id, :num_boards, :max_dead_boards, :priority)
+ """;
/** Create a request to allocate a rectangle of boards. */
@Parameter("job_id")
@@ -296,20 +334,22 @@ public abstract class SQLQueries {
@Parameter("max_dead_boards")
@Parameter("priority")
@GeneratesID
- protected static final String INSERT_REQ_SIZE =
- "INSERT INTO job_request(job_id, width, height, max_dead_boards, "
- + "priority) "
- + "VALUES (:job_id, :width, :height, :max_dead_boards, "
- + ":priority)";
+ protected static final String INSERT_REQ_SIZE = """
+ INSERT INTO job_request(
+ job_id, width, height, max_dead_boards, priority)
+ VALUES (:job_id, :width, :height, :max_dead_boards, :priority)
+ """;
/** Create a request to allocate a specific board. */
@Parameter("job_id")
@Parameter("board_id")
@Parameter("priority")
@GeneratesID
- protected static final String INSERT_REQ_BOARD =
- "INSERT INTO job_request(job_id, board_id, priority) "
- + "VALUES (:job_id, :board_id, :priority)";
+ protected static final String INSERT_REQ_BOARD = """
+ INSERT INTO job_request(
+ job_id, board_id, priority)
+ VALUES (:job_id, :board_id, :priority)
+ """;
/** Create a request to allocate triads starting at a particular board. */
@Parameter("job_id")
@@ -319,24 +359,31 @@ public abstract class SQLQueries {
@Parameter("max_dead_boards")
@Parameter("priority")
@GeneratesID
- protected static final String INSERT_REQ_SIZE_BOARD = "INSERT INTO "
- + "job_request(job_id, board_id, width, height, max_dead_boards, "
- + "priority) "
- + "VALUES(:job_id, :board_id, :width, :height, :max_dead_boards,"
- + ":priority)";
-
- /** Increases the importance of a job. */
- protected static final String BUMP_IMPORTANCE =
- "UPDATE job_request SET importance = importance + priority";
+ protected static final String INSERT_REQ_SIZE_BOARD = """
+ INSERT INTO job_request(
+ job_id, board_id, width, height, max_dead_boards, priority)
+ VALUES (:job_id, :board_id, :width, :height, :max_dead_boards,
+ :priority)
+ """;
+
+ /** Increases the importance of all current job allocation requests. */
+ protected static final String BUMP_IMPORTANCE = """
+ UPDATE job_request
+ SET importance = importance + priority
+ """;
/** Get the address of the BMP of the root board of the machine. */
@Parameter("machine_id")
@ResultColumn("address")
@SingleRowResult
- protected static final String GET_ROOT_BMP_ADDRESS =
- "SELECT bmp.address FROM bmp JOIN boards USING (bmp_id) "
- + "WHERE boards.machine_id = :machine_id "
- + "AND boards.x = 0 AND boards.y = 0 LIMIT 1";
+ protected static final String GET_ROOT_BMP_ADDRESS = """
+ SELECT bmp.address
+ FROM bmp
+ JOIN boards USING (bmp_id)
+ WHERE boards.machine_id = :machine_id
+ AND boards.x = 0 AND boards.y = 0
+ LIMIT 1
+ """;
/** Get the address of the BMP of the root board of the machine. */
@Parameter("machine_id")
@@ -344,9 +391,13 @@ public abstract class SQLQueries {
@Parameter("frame")
@ResultColumn("address")
@SingleRowResult
- protected static final String GET_BMP_ADDRESS =
- "SELECT address FROM bmp WHERE machine_id = :machine_id "
- + "AND cabinet = :cabinet AND frame = :frame LIMIT 1";
+ protected static final String GET_BMP_ADDRESS = """
+ SELECT address
+ FROM bmp
+ WHERE machine_id = :machine_id
+ AND cabinet = :cabinet AND frame = :frame
+ LIMIT 1
+ """;
/** Get all the BMPs. */
@ResultColumn("bmp_id")
@@ -354,36 +405,47 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("cabinet")
@ResultColumn("frame")
- protected static final String GET_ALL_BMPS =
- "SELECT bmp_id, machine_name, address, cabinet, frame FROM bmp "
- + "JOIN machines on bmp.machine_id = machines.machine_id";
+ protected static final String GET_ALL_BMPS = """
+ SELECT bmp_id, machine_name, address, cabinet, frame
+ FROM bmp
+ JOIN machines on bmp.machine_id = machines.machine_id
+ """;
/** Get all the boards of a BMP. */
@Parameter("bmp_id")
@ResultColumn("board_id")
@ResultColumn("board_num")
@ResultColumn("address")
- protected static final String GET_ALL_BMP_BOARDS =
- "SELECT board_id, board_num, address FROM boards "
- + "WHERE bmp_id = :bmp_id";
+ protected static final String GET_ALL_BMP_BOARDS = """
+ SELECT board_id, board_num, address
+ FROM boards
+ WHERE bmp_id = :bmp_id
+ """;
/** Get the address of the root chip of a board. */
@Parameter("board_id")
@ResultColumn("address")
@SingleRowResult
- protected static final String GET_BOARD_ADDRESS =
- "SELECT address FROM boards WHERE board_id = :board_id LIMIT 1";
+ protected static final String GET_BOARD_ADDRESS = """
+ SELECT address
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/**
* Get the boards of a machine that can be used. Excludes disabled boards.
*/
@Parameter("machine_id")
@ResultColumn("board_num")
- protected static final String GET_BOARD_NUMBERS =
- "SELECT board_num FROM boards WHERE machine_id = :machine_id "
- + "AND board_num IS NOT NULL "
- + "AND (functioning IS NULL OR functioning != 0) "
- + "ORDER BY board_num ASC";
+ protected static final String GET_BOARD_NUMBERS = """
+ SELECT board_num
+ FROM boards
+ WHERE machine_id = :machine_id
+ AND board_num IS NOT NULL
+ AND (functioning IS NULL OR functioning != 0)
+ ORDER BY board_num ASC
+ """;
/**
* Get the boards of a BMP that can be used. Excludes disabled boards.
@@ -392,13 +454,16 @@ public abstract class SQLQueries {
@Parameter("cabinet")
@Parameter("frame")
@ResultColumn("board_num")
- protected static final String GET_BMP_BOARD_NUMBERS =
- "SELECT board_num FROM boards JOIN bmp USING (bmp_id) "
- + "WHERE boards.machine_id = :machine_id "
- + "AND cabinet = :cabinet AND frame = :frame "
- + "AND board_num IS NOT NULL "
- + "AND (functioning IS NULL OR functioning != 0) "
- + "ORDER BY board_num ASC";
+ protected static final String GET_BMP_BOARD_NUMBERS = """
+ SELECT board_num
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE boards.machine_id = :machine_id
+ AND cabinet = :cabinet AND frame = :frame
+ AND board_num IS NOT NULL
+ AND (functioning IS NULL OR functioning != 0)
+ ORDER BY board_num ASC
+ """;
/**
* Get the boards (and related info) of a machine that are in service.
@@ -414,13 +479,16 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_LIVE_BOARDS =
- "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, "
- + "boards.address, bmp_id, boards.machine_id FROM boards "
- + "JOIN bmp USING (bmp_id) "
- + "WHERE boards.machine_id = :machine_id "
- + "AND board_num IS NOT NULL "
- + "AND functioning = 1 ORDER BY z ASC, x ASC, y ASC";
+ protected static final String GET_LIVE_BOARDS = """
+ SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num,
+ boards.address, bmp_id, boards.machine_id
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE boards.machine_id = :machine_id
+ AND board_num IS NOT NULL
+ AND functioning = 1
+ ORDER BY z ASC, x ASC, y ASC
+ """;
/**
* Get the boards (and related info) of a machine that have been disabled.
@@ -436,13 +504,15 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_DEAD_BOARDS =
- "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, "
- + "boards.address, bmp_id, boards.machine_id FROM boards "
- + "JOIN bmp USING (bmp_id) "
- + "WHERE boards.machine_id = :machine_id "
- + "AND (board_num IS NULL OR functioning = 0) "
- + "ORDER BY z ASC, x ASC, y ASC";
+ protected static final String GET_DEAD_BOARDS = """
+ SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num,
+ boards.address, bmp_id, boards.machine_id
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE boards.machine_id = :machine_id
+ AND (board_num IS NULL OR functioning = 0)
+ ORDER BY z ASC, x ASC, y ASC
+ """;
/**
* Get all the boards (and related info) of a machine.
@@ -460,13 +530,15 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_ALL_BOARDS =
- "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, "
- + "boards.address, bmp_id, boards.machine_id FROM boards "
- + "JOIN bmp USING (bmp_id) "
- + "WHERE boards.machine_id = :machine_id "
- + "AND board_num IS NOT NULL "
- + "ORDER BY z ASC, x ASC, y ASC";
+ protected static final String GET_ALL_BOARDS = """
+ SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num,
+ boards.address, bmp_id, boards.machine_id
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE boards.machine_id = :machine_id
+ AND board_num IS NOT NULL
+ ORDER BY z ASC, x ASC, y ASC
+ """;
/**
* Get all the boards (and related info) known to the service.
@@ -483,12 +555,14 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_ALL_BOARDS_OF_ALL_MACHINES =
- "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, "
- + "boards.address, bmp_id, boards.machine_id FROM boards "
- + "JOIN bmp USING (bmp_id) "
- + "WHERE board_num IS NOT NULL "
- + "ORDER BY z ASC, x ASC, y ASC";
+ protected static final String GET_ALL_BOARDS_OF_ALL_MACHINES = """
+ SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num,
+ boards.address, bmp_id, boards.machine_id
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE board_num IS NOT NULL
+ ORDER BY z ASC, x ASC, y ASC
+ """;
/**
* Get the coords of boards assigned to a job.
@@ -504,31 +578,36 @@ public abstract class SQLQueries {
@ResultColumn("address")
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
- protected static final String GET_JOB_BOARD_COORDS =
- "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, "
- + "boards.address, bmp_id, boards.machine_id FROM boards "
- + "JOIN bmp USING (bmp_id) "
- + "WHERE boards.allocated_job = :job_id "
- + "ORDER BY z ASC, x ASC, y ASC";
+ protected static final String GET_JOB_BOARD_COORDS = """
+ SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num,
+ boards.address, bmp_id, boards.machine_id
+ FROM boards
+ JOIN bmp USING (bmp_id)
+ WHERE boards.allocated_job = :job_id
+ ORDER BY z ASC, x ASC, y ASC
+ """;
/** Get basic info about active jobs on a machine. */
@Parameter("machine_id")
@ResultColumn("job_id")
@ResultColumn("owner_name")
- protected static final String GET_MACHINE_JOBS =
- "SELECT job_id, user_info.user_name AS owner_name FROM jobs "
- + "JOIN user_info ON jobs.owner = user_info.user_id "
- + "WHERE machine_id = :machine_id AND job_state != 4 "
- // job is not DESTROYED
- + "ORDER BY job_id ASC";
+ protected static final String GET_MACHINE_JOBS = """
+ SELECT job_id, user_info.user_name AS owner_name
+ FROM jobs
+ JOIN user_info ON jobs.owner = user_info.user_id
+ WHERE machine_id = :machine_id
+ AND job_state != 4 -- job is not DESTROYED
+ ORDER BY job_id ASC
+ """;
/** Get the boards that are available for allocation. */
@Parameter("machine_id")
@ResultColumn("board_num")
- protected static final String GET_AVAILABLE_BOARD_NUMBERS =
- "SELECT board_num FROM boards "
- + "WHERE machine_id = :machine_id AND may_be_allocated "
- + "ORDER BY board_num ASC";
+ protected static final String GET_AVAILABLE_BOARD_NUMBERS = """
+ SELECT board_num FROM boards
+ WHERE machine_id = :machine_id AND may_be_allocated
+ ORDER BY board_num ASC
+ """;
/**
* Get a machine's tags. Theoretically when selecting a machine by tags we
@@ -538,32 +617,41 @@ public abstract class SQLQueries {
*/
@Parameter("machine_id")
@ResultColumn("tag")
- protected static final String GET_TAGS =
- "SELECT tag FROM tags WHERE machine_id = :machine_id";
+ protected static final String GET_TAGS = """
+ SELECT tag
+ FROM tags
+ WHERE machine_id = :machine_id
+ """;
/** Update the keepalive timestamp. */
@Parameter("keepalive_host")
@Parameter("job_id")
- protected static final String UPDATE_KEEPALIVE =
- "UPDATE jobs SET keepalive_timestamp = UNIX_TIMESTAMP(), "
- + "keepalive_host = :keepalive_host WHERE job_id = :job_id "
- + "AND job_state != 4"; // DESTROYED
+ protected static final String UPDATE_KEEPALIVE = """
+ UPDATE jobs
+ SET keepalive_timestamp = UNIX_TIMESTAMP(),
+ keepalive_host = :keepalive_host
+ WHERE job_id = :job_id AND job_state != 4 -- job is not DESTROYED
+ """;
/** Mark a job as dead. */
@Parameter("death_reason")
@Parameter("job_id")
- protected static final String DESTROY_JOB =
- "UPDATE jobs SET job_state = 4, death_reason = :death_reason, "
- // 4 = DESTROYED
- + "death_timestamp = UNIX_TIMESTAMP() "
- + "WHERE job_id = :job_id AND job_state != 4";
+ protected static final String DESTROY_JOB = """
+ UPDATE jobs
+ SET job_state = 4, -- job becomes DESTROYED
+ death_reason = :death_reason,
+ death_timestamp = UNIX_TIMESTAMP()
+ WHERE job_id = :job_id AND job_state != 4 -- job is not DESTROYED
+ """;
/** Record the reason for a job being destroyed. */
@Parameter("death_reason")
@Parameter("job_id")
- protected static final String NOTE_DESTROY_REASON =
- "UPDATE jobs SET death_reason = :death_reason "
- + "WHERE job_id = :job_id";
+ protected static final String NOTE_DESTROY_REASON = """
+ UPDATE jobs
+ SET death_reason = :death_reason
+ WHERE job_id = :job_id
+ """;
/**
* Get the number of boards that are allocated to a job that are switched
@@ -572,9 +660,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@ResultColumn("total_on")
@SingleRowResult
- protected static final String GET_SUM_BOARDS_POWERED =
- "SELECT COALESCE(sum(board_power), 0) AS total_on FROM boards "
- + "WHERE allocated_job = :job_id";
+ protected static final String GET_SUM_BOARDS_POWERED = """
+ SELECT COALESCE(sum(board_power), 0) AS total_on
+ FROM boards
+ WHERE allocated_job = :job_id
+ """;
/** Get connection info for board allocated to a job. */
@Parameter("job_id")
@@ -585,13 +675,14 @@ public abstract class SQLQueries {
@ResultColumn("z")
@ResultColumn("root_x")
@ResultColumn("root_y")
- protected static final String GET_BOARD_CONNECT_INFO =
- "SELECT board_id, address, x, y, z, root_x, root_y "
- + "FROM boards JOIN jobs "
- + "ON boards.allocated_job = jobs.job_id "
- + "WHERE allocated_job = :job_id "
- + "AND jobs.job_state != 4 " // DESTROYED
- + "ORDER BY x ASC, y ASC";
+ protected static final String GET_BOARD_CONNECT_INFO = """
+ SELECT board_id, address, x, y, z, root_x, root_y
+ FROM boards
+ JOIN jobs ON boards.allocated_job = jobs.job_id
+ WHERE allocated_job = :job_id
+ AND jobs.job_state != 4 -- job is not DESTROYED
+ ORDER BY x ASC, y ASC
+ """;
/** Get the coordinates of a board. */
@Parameter("board_id")
@@ -601,9 +692,12 @@ public abstract class SQLQueries {
@ResultColumn("root_x")
@ResultColumn("root_y")
@SingleRowResult
- protected static final String GET_ROOT_COORDS =
- "SELECT x, y, z, root_x, root_y FROM boards "
- + "WHERE board_id = :board_id LIMIT 1";
+ protected static final String GET_ROOT_COORDS = """
+ SELECT x, y, z, root_x, root_y
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/** Get whether a board is powered. */
@Parameter("board_id")
@@ -611,17 +705,23 @@ public abstract class SQLQueries {
@ResultColumn("power_off_timestamp")
@ResultColumn("power_on_timestamp")
@SingleRowResult
- protected static final String GET_BOARD_POWER_INFO =
- "SELECT board_power, power_off_timestamp, power_on_timestamp "
- + "FROM boards WHERE board_id = :board_id LIMIT 1";
+ protected static final String GET_BOARD_POWER_INFO = """
+ SELECT board_power, power_off_timestamp, power_on_timestamp
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/** Get What job is allocated to a board. */
@Parameter("board_id")
@ResultColumn("allocated_job")
@SingleRowResult
- protected static final String GET_BOARD_JOB =
- "SELECT allocated_job FROM boards WHERE board_id = :board_id "
- + "LIMIT 1";
+ protected static final String GET_BOARD_JOB = """
+ SELECT allocated_job
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/**
* Get the problem reports about boards in a machine.
@@ -634,13 +734,15 @@ public abstract class SQLQueries {
@ResultColumn("reported_issue")
@ResultColumn("report_timestamp")
@ResultColumn("reporter_name")
- protected static final String GET_MACHINE_REPORTS =
- "SELECT board_id, report_id, reported_issue, report_timestamp, "
- + "user_name AS reporter_name "
- + "FROM board_reports JOIN user_info ON reporter = user_id "
- + "JOIN boards USING (board_id) "
- + "WHERE machine_id = :machine_id "
- + "ORDER BY board_id, report_id";
+ protected static final String GET_MACHINE_REPORTS = """
+ SELECT board_id, report_id, reported_issue, report_timestamp,
+ user_name AS reporter_name
+ FROM board_reports
+ JOIN user_info ON reporter = user_id
+ JOIN boards USING (board_id)
+ WHERE machine_id = :machine_id
+ ORDER BY board_id, report_id
+ """;
/**
* Get the problem reports about a board.
@@ -653,16 +755,20 @@ public abstract class SQLQueries {
@ResultColumn("reported_issue")
@ResultColumn("report_timestamp")
@ResultColumn("reporter_name")
- protected static final String GET_BOARD_REPORTS =
- "SELECT board_id, report_id, reported_issue, report_timestamp, "
- + "user_name AS reporter_name "
- + "FROM board_reports JOIN user_info ON reporter = user_id "
- + "WHERE board_id = :board_id";
+ protected static final String GET_BOARD_REPORTS = """
+ SELECT board_id, report_id, reported_issue, report_timestamp,
+ user_name AS reporter_name
+ FROM board_reports
+ JOIN user_info ON reporter = user_id
+ WHERE board_id = :board_id
+ """;
/** Delete an allocation task. */
@Parameter("request_id")
- protected static final String DELETE_TASK =
- "DELETE FROM job_request WHERE req_id = :request_id";
+ protected static final String DELETE_TASK = """
+ DELETE FROM job_request
+ WHERE req_id = :request_id
+ """;
/** Find a single free board. */
@Parameter("machine_id")
@@ -670,10 +776,13 @@ public abstract class SQLQueries {
@ResultColumn("y")
@ResultColumn("z")
@SingleRowResult
- protected static final String FIND_FREE_BOARD =
- "SELECT x, y, z FROM boards "
- + "WHERE machine_id = :machine_id AND may_be_allocated "
- + "ORDER BY power_off_timestamp ASC LIMIT 1";
+ protected static final String FIND_FREE_BOARD = """
+ SELECT x, y, z
+ FROM boards
+ WHERE machine_id = :machine_id AND may_be_allocated
+ ORDER BY power_off_timestamp ASC
+ LIMIT 1
+ """;
/**
* Tell a job that it is allocated. Doesn't set the state.
@@ -688,25 +797,30 @@ public abstract class SQLQueries {
@Parameter("num_boards")
@Parameter("allocated_board_id")
@Parameter("job_id")
- protected static final String ALLOCATE_BOARDS_JOB = "UPDATE jobs SET "
- + "width = :width, height = :height, depth = :depth, "
- + "num_pending = 0, root_id = :board_id, "
- + "allocation_size = :num_boards, "
- + "allocation_timestamp = UNIX_TIMESTAMP(), "
- + "allocated_root = :allocated_board_id "
- + "WHERE job_id = :job_id";
-
- /** Get a board's ID by its coordinates. */
+ protected static final String ALLOCATE_BOARDS_JOB = """
+ UPDATE jobs
+ SET width = :width, height = :height, depth = :depth,
+ num_pending = 0, root_id = :board_id,
+ allocation_size = :num_boards,
+ allocation_timestamp = UNIX_TIMESTAMP(),
+ allocated_root = :allocated_board_id
+ WHERE job_id = :job_id
+ """;
+
+ /** Get an available board's ID by its coordinates. */
@Parameter("machine_id")
@Parameter("x")
@Parameter("y")
@Parameter("z")
@ResultColumn("board_id")
@SingleRowResult
- protected static final String GET_BOARD_BY_COORDS =
- "SELECT board_id FROM boards WHERE machine_id = :machine_id "
- + "AND x = :x AND y = :y AND z = :z "
- + "AND may_be_allocated LIMIT 1";
+ protected static final String GET_BOARD_BY_COORDS = """
+ SELECT board_id
+ FROM boards
+ WHERE machine_id = :machine_id AND x = :x AND y = :y AND z = :z
+ AND may_be_allocated
+ LIMIT 1
+ """;
/**
* Tell a board that it is allocated.
@@ -715,9 +829,11 @@ public abstract class SQLQueries {
*/
@Parameter("job_id")
@Parameter("board_id")
- protected static final String ALLOCATE_BOARDS_BOARD =
- "UPDATE boards SET allocated_job = :job_id "
- + "WHERE board_id = :board_id";
+ protected static final String ALLOCATE_BOARDS_BOARD = """
+ UPDATE boards
+ SET allocated_job = :job_id
+ WHERE board_id = :board_id
+ """;
/**
* Tell the boards of a job that they're no longer allocated to the job.
@@ -726,27 +842,34 @@ public abstract class SQLQueries {
*/
@Parameter("job_id")
@Parameter("bmp_id")
- protected static final String DEALLOCATE_BMP_BOARDS_JOB =
- "UPDATE boards SET allocated_job = NULL "
- + "WHERE allocated_job = :job_id AND bmp_id = :bmp_id";
+ protected static final String DEALLOCATE_BMP_BOARDS_JOB = """
+ UPDATE boards
+ SET allocated_job = NULL
+ WHERE allocated_job = :job_id
+ AND bmp_id = :bmp_id
+ """;
/**
- * Set the power state of a board.
+ * Set the power state of a board to ON.
*/
@Parameter("board_id")
- protected static final String SET_BOARD_POWER_ON =
- "UPDATE boards SET board_power = 1, "
- + "power_on_timestamp = UNIX_TIMESTAMP() "
- + "WHERE board_id = :board_id";
+ protected static final String SET_BOARD_POWER_ON = """
+ UPDATE boards
+ SET board_power = 1,
+ power_on_timestamp = UNIX_TIMESTAMP()
+ WHERE board_id = :board_id
+ """;
/**
- * Set the power state of a board.
+ * Set the power state of a board to OFF.
*/
@Parameter("board_id")
- protected static final String SET_BOARD_POWER_OFF =
- "UPDATE boards SET board_power = 0, "
- + "power_off_timestamp = UNIX_TIMESTAMP() "
- + "WHERE board_id = :board_id";
+ protected static final String SET_BOARD_POWER_OFF = """
+ UPDATE boards
+ SET board_power = 0,
+ power_off_timestamp = UNIX_TIMESTAMP()
+ WHERE board_id = :board_id
+ """;
/**
* Find jobs that have expired their keepalive interval.
@@ -754,11 +877,11 @@ public abstract class SQLQueries {
* @see AllocatorTask
*/
@ResultColumn("job_id")
- protected static final String FIND_EXPIRED_JOBS = //
- "SELECT job_id FROM jobs " //
- + "WHERE job_state != 4 " // DESTROYED
- + "AND keepalive_timestamp + keepalive_interval < "
- + "UNIX_TIMESTAMP()";
+ protected static final String FIND_EXPIRED_JOBS = """
+ SELECT job_id FROM jobs
+ WHERE job_state != 4 -- job is not DESTROYED
+ AND keepalive_timestamp + keepalive_interval < UNIX_TIMESTAMP()
+ """;
/**
* Set the state and number of pending changes for a job.
@@ -768,9 +891,11 @@ public abstract class SQLQueries {
@Parameter("job_state")
@Parameter("num_pending")
@Parameter("job_id")
- protected static final String SET_STATE_PENDING =
- "UPDATE jobs SET job_state = :job_state, "
- + "num_pending = :num_pending WHERE job_id = :job_id";
+ protected static final String SET_STATE_PENDING = """
+ UPDATE jobs
+ SET job_state = :job_state, num_pending = :num_pending
+ WHERE job_id = :job_id
+ """;
/**
* Set the state destroyed and number of pending changes for a job.
@@ -779,24 +904,30 @@ public abstract class SQLQueries {
*/
@Parameter("num_pending")
@Parameter("job_id")
- protected static final String SET_STATE_DESTROYED =
- "UPDATE jobs SET job_state = 4, "
- + "num_pending = :num_pending, "
- + "death_timestamp = UNIX_TIMESTAMP() "
- + "WHERE job_id = :job_id";
+ protected static final String SET_STATE_DESTROYED = """
+ UPDATE jobs
+ SET job_state = 4,
+ num_pending = :num_pending,
+ death_timestamp = UNIX_TIMESTAMP()
+ WHERE job_id = :job_id
+ """;
/** Delete a request to allocate resources for a job. */
@Parameter("job_id")
- protected static final String KILL_JOB_ALLOC_TASK =
- "DELETE FROM job_request WHERE job_id = :job_id";
+ protected static final String KILL_JOB_ALLOC_TASK = """
+ DELETE FROM job_request
+ WHERE job_id = :job_id
+ """;
/**
* Delete a request to change the power of a board. Used once the change has
* been completed.
*/
@Parameter("change_id")
- protected static final String FINISHED_PENDING =
- "DELETE FROM pending_changes WHERE change_id = :change_id";
+ protected static final String FINISHED_PENDING = """
+ DELETE FROM pending_changes
+ WHERE change_id = :change_id
+ """;
/**
* Get descriptions of how to move from a board to its neighbours.
@@ -808,8 +939,10 @@ public abstract class SQLQueries {
@ResultColumn("dx")
@ResultColumn("dy")
@ResultColumn("dz")
- protected static final String LOAD_DIR_INFO =
- "SELECT z, direction, dx, dy, dz FROM movement_directions";
+ protected static final String LOAD_DIR_INFO = """
+ SELECT z, direction, dx, dy, dz
+ FROM movement_directions
+ """;
/**
* Get the requests to change the power of boards on a BMP.
@@ -829,13 +962,15 @@ public abstract class SQLQueries {
@ResultColumn("to_state")
@ResultColumn("board_num")
@ResultColumn("bmp_id")
- protected static final String GET_CHANGES =
- "SELECT change_id, job_id, pending_changes.board_id, power, "
- + "fpga_n, fpga_s, fpga_e, fpga_w, fpga_se, fpga_nw, "
- + "from_state, to_state, board_num, bmp_id "
- + "FROM pending_changes JOIN boards USING (board_id) "
- + "WHERE bmp_id = :bmp_id "
- + "ORDER BY change_id";
+ protected static final String GET_CHANGES = """
+ SELECT change_id, job_id, pending_changes.board_id, power,
+ fpga_n, fpga_s, fpga_e, fpga_w, fpga_se, fpga_nw,
+ from_state, to_state, board_num, bmp_id
+ FROM pending_changes
+ JOIN boards USING (board_id)
+ WHERE bmp_id = :bmp_id
+ ORDER BY change_id
+ """;
/**
* Get the number of changes that are not completed for a job.
@@ -844,10 +979,13 @@ public abstract class SQLQueries {
@Parameter("from_state")
@Parameter("to_state")
@ResultColumn("n_changes")
- protected static final String COUNT_CHANGES_FOR_JOB =
- "SELECT COUNT(change_id) as n_changes from pending_changes "
- + "WHERE job_id = :job_id AND from_state = :from_state "
- + "AND to_state = :to_state";
+ protected static final String COUNT_CHANGES_FOR_JOB = """
+ SELECT COUNT(change_id) AS n_changes
+ FROM pending_changes
+ WHERE job_id = :job_id
+ AND from_state = :from_state
+ AND to_state = :to_state
+ """;
/**
* Insert a BMP.
@@ -859,9 +997,11 @@ public abstract class SQLQueries {
@Parameter("cabinet")
@Parameter("frame")
@GeneratesID
- protected static final String INSERT_BMP =
- "INSERT INTO bmp(machine_id, address, cabinet, frame) "
- + "VALUES(:machine_id, :address, :cabinet, :frame)";
+ protected static final String INSERT_BMP = """
+ INSERT INTO bmp(
+ machine_id, address, cabinet, frame)
+ VALUES(:machine_id, :address, :cabinet, :frame)
+ """;
/**
* Insert a board.
@@ -879,11 +1019,14 @@ public abstract class SQLQueries {
@Parameter("root_y")
@Parameter("enabled")
@GeneratesID
- protected static final String INSERT_BOARD = "INSERT INTO boards("
- + "machine_id, address, bmp_id, board_num, x, y, z, "
- + "root_x, root_y, functioning) VALUES("
- + ":machine_id, :address, :bmp_id, :board_num, :x, :y, :z, "
- + ":root_x, :root_y, :enabled)";
+ protected static final String INSERT_BOARD = """
+ INSERT INTO boards(
+ machine_id, address, bmp_id, board_num, x, y, z,
+ root_x, root_y, functioning)
+ VALUES(
+ :machine_id, :address, :bmp_id, :board_num, :x, :y, :z,
+ :root_x, :root_y, :enabled)
+ """;
/**
* Insert a link.
@@ -896,9 +1039,11 @@ public abstract class SQLQueries {
@Parameter("dir_2")
@Parameter("live")
@GeneratesID
- protected static final String INSERT_LINK =
- "INSERT IGNORE INTO links(board_1, dir_1, board_2, dir_2, live) "
- + "VALUES (:board_1, :dir_1, :board_2, :dir_2, :live)";
+ protected static final String INSERT_LINK = """
+ INSERT IGNORE INTO links(
+ board_1, dir_1, board_2, dir_2, live)
+ VALUES (:board_1, :dir_1, :board_2, :dir_2, :live)
+ """;
/**
* Insert a machine.
@@ -910,10 +1055,11 @@ public abstract class SQLQueries {
@Parameter("height")
@Parameter("depth")
@GeneratesID
- protected static final String INSERT_MACHINE_SPINN_5 =
- "INSERT INTO machines(machine_name, "
- + "width, height, depth, board_model) "
- + "VALUES(:name, :width, :height, :depth, 5)";
+ protected static final String INSERT_MACHINE_SPINN_5 = """
+ INSERT INTO machines(
+ machine_name, width, height, depth, board_model)
+ VALUES(:name, :width, :height, :depth, 5)
+ """;
/**
* Insert a tag.
@@ -924,8 +1070,11 @@ public abstract class SQLQueries {
@Parameter("machine_id")
@Parameter("tag")
@GeneratesID
- protected static final String INSERT_TAG =
- "INSERT INTO tags(machine_id, tag) VALUES(:machine_id, :tag)";
+ protected static final String INSERT_TAG = """
+ INSERT INTO tags(
+ machine_id, tag)
+ VALUES(:machine_id, :tag)
+ """;
/**
* Delete all tags for a machine.
@@ -933,8 +1082,10 @@ public abstract class SQLQueries {
* @see MachineStateControl
*/
@Parameter("machine_id")
- protected static final String DELETE_MACHINE_TAGS =
- "DELETE FROM tags WHERE machine_id = :machine_id";
+ protected static final String DELETE_MACHINE_TAGS = """
+ DELETE FROM tags
+ WHERE machine_id = :machine_id
+ """;
/**
* Set the in-service flag for a machine.
@@ -943,9 +1094,11 @@ public abstract class SQLQueries {
*/
@Parameter("in_service")
@Parameter("machine_name")
- protected static final String SET_MACHINE_STATE =
- "UPDATE machines SET in_service = :in_service "
- + "WHERE machine_name = :machine_name";
+ protected static final String SET_MACHINE_STATE = """
+ UPDATE machines
+ SET in_service = :in_service
+ WHERE machine_name = :machine_name
+ """;
/**
* Note down the maximum chip coordinates so we can calculate wraparounds
@@ -956,9 +1109,11 @@ public abstract class SQLQueries {
@Parameter("max_x")
@Parameter("max_y")
@Parameter("machine_id")
- protected static final String SET_MAX_COORDS =
- "UPDATE machines SET max_chip_x = :max_x, max_chip_y = :max_y "
- + "WHERE machine_id = :machine_id";
+ protected static final String SET_MAX_COORDS = """
+ UPDATE machines
+ SET max_chip_x = :max_x, max_chip_y = :max_y
+ WHERE machine_id = :machine_id
+ """;
/** Get a board's full coordinate info given it's ID. */
@Parameter("board_id")
@@ -976,15 +1131,18 @@ public abstract class SQLQueries {
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
@SingleRowResult
- protected static final String FIND_BOARD_BY_ID =
- "SELECT boards.board_id, boards.x, boards.y, boards.z, "
- + "bmp.cabinet, bmp.frame, board_num, boards.address, "
- + "machines.machine_name, bmp_serial_id, "
- + "physical_serial_id, bmp_id, boards.machine_id "
- + "FROM boards JOIN machines USING (machine_id) "
- + "JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE boards.board_id = :board_id LIMIT 1";
+ protected static final String FIND_BOARD_BY_ID = """
+ SELECT boards.board_id, boards.x, boards.y, boards.z,
+ bmp.cabinet, bmp.frame, board_num, boards.address,
+ machines.machine_name, bmp_serial_id,
+ physical_serial_id, bmp_id, boards.machine_id
+ FROM boards
+ JOIN machines USING (machine_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE boards.board_id = :board_id
+ LIMIT 1
+ """;
/** Get a board's ID given it's triad coordinates. */
@Parameter("machine_name")
@@ -1005,16 +1163,19 @@ public abstract class SQLQueries {
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
@SingleRowResult
- protected static final String FIND_BOARD_BY_NAME_AND_XYZ =
- "SELECT boards.board_id, boards.x, boards.y, boards.z, "
- + "bmp.cabinet, bmp.frame, board_num, boards.address, "
- + "machines.machine_name, bmp_serial_id, "
- + "physical_serial_id, bmp_id, boards.machine_id "
- + "FROM boards JOIN machines USING (machine_id) "
- + "JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE machine_name = :machine_name "
- + "AND x = :x AND y = :y AND z = :z LIMIT 1";
+ protected static final String FIND_BOARD_BY_NAME_AND_XYZ = """
+ SELECT boards.board_id, boards.x, boards.y, boards.z,
+ bmp.cabinet, bmp.frame, board_num, boards.address,
+ machines.machine_name, bmp_serial_id,
+ physical_serial_id, bmp_id, boards.machine_id
+ FROM boards
+ JOIN machines USING (machine_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE machine_name = :machine_name
+ AND x = :x AND y = :y AND z = :z
+ LIMIT 1
+ """;
/** Get a board's ID given it's physical coordinates. */
@Parameter("machine_name")
@@ -1035,18 +1196,21 @@ public abstract class SQLQueries {
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
@SingleRowResult
- protected static final String FIND_BOARD_BY_NAME_AND_CFB =
- "SELECT boards.board_id, boards.x, boards.y, boards.z, "
- + "bmp.cabinet, bmp.frame, board_num, boards.address, "
- + "machines.machine_name, bmp_serial_id, "
- + "physical_serial_id, bmp_id, boards.machine_id "
- + "FROM boards JOIN machines USING (machine_id) "
- + "JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE machine_name = :machine_name "
- + "AND bmp.cabinet = :cabinet AND bmp.frame = :frame "
- + "AND boards.board_num IS NOT NULL "
- + "AND boards.board_num = :board LIMIT 1";
+ protected static final String FIND_BOARD_BY_NAME_AND_CFB = """
+ SELECT boards.board_id, boards.x, boards.y, boards.z,
+ bmp.cabinet, bmp.frame, board_num, boards.address,
+ machines.machine_name, bmp_serial_id,
+ physical_serial_id, bmp_id, boards.machine_id
+ FROM boards
+ JOIN machines USING (machine_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE machine_name = :machine_name
+ AND bmp.cabinet = :cabinet AND bmp.frame = :frame
+ AND boards.board_num IS NOT NULL
+ AND boards.board_num = :board
+ LIMIT 1
+ """;
/** Get a board's ID given it's IP address. */
@Parameter("machine_name")
@@ -1065,17 +1229,20 @@ public abstract class SQLQueries {
@ResultColumn("bmp_id")
@ResultColumn("machine_id")
@SingleRowResult
- protected static final String FIND_BOARD_BY_NAME_AND_IP_ADDRESS =
- "SELECT boards.board_id, boards.x, boards.y, boards.z, "
- + "bmp.cabinet, bmp.frame, board_num, boards.address, "
- + "machines.machine_name, bmp_serial_id, "
- + "physical_serial_id, bmp_id, boards.machine_id "
- + "FROM boards JOIN machines USING (machine_id) "
- + "JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE machine_name = :machine_name "
- + "AND boards.address IS NOT NULL "
- + "AND boards.address = :address LIMIT 1";
+ protected static final String FIND_BOARD_BY_NAME_AND_IP_ADDRESS = """
+ SELECT boards.board_id, boards.x, boards.y, boards.z,
+ bmp.cabinet, bmp.frame, board_num, boards.address,
+ machines.machine_name, bmp_serial_id,
+ physical_serial_id, bmp_id, boards.machine_id
+ FROM boards
+ JOIN machines USING (machine_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE machine_name = :machine_name
+ AND boards.address IS NOT NULL
+ AND boards.address = :address
+ LIMIT 1
+ """;
/**
* Get the value of a board's {@code functioning} column.
@@ -1085,9 +1252,12 @@ public abstract class SQLQueries {
@Parameter("board_id")
@ResultColumn("functioning")
@SingleRowResult
- protected static final String GET_FUNCTIONING_FIELD =
- "SELECT functioning FROM boards "
- + "WHERE board_id = :board_id LIMIT 1";
+ protected static final String GET_FUNCTIONING_FIELD = """
+ SELECT functioning
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/**
* Set the value of a board's {@code functioning} column. Enables or
@@ -1097,9 +1267,11 @@ public abstract class SQLQueries {
*/
@Parameter("enabled")
@Parameter("board_id")
- protected static final String SET_FUNCTIONING_FIELD =
- "UPDATE boards SET functioning = :enabled "
- + "WHERE board_id = :board_id";
+ protected static final String SET_FUNCTIONING_FIELD = """
+ UPDATE boards
+ SET functioning = :enabled
+ WHERE board_id = :board_id
+ """;
/**
* Get the quota for a user.
@@ -1110,10 +1282,14 @@ public abstract class SQLQueries {
@ResultColumn("quota_total")
@ResultColumn("user_id")
@SingleRowResult
- protected static final String GET_USER_QUOTA =
- "SELECT SUM(quota) AS quota_total, quotas.user_id FROM quotas "
- + "JOIN user_info USING (user_id) "
- + "WHERE user_info.user_name = :user_name AND user_id IS NOT NULL";
+ protected static final String GET_USER_QUOTA = """
+ SELECT
+ SUM(quota) AS quota_total,
+ quotas.user_id
+ FROM quotas
+ JOIN user_info USING (user_id)
+ WHERE user_info.user_name = :user_name AND user_id IS NOT NULL
+ """;
/**
* Get the quota for a group.
@@ -1123,8 +1299,11 @@ public abstract class SQLQueries {
@Parameter("group_id")
@ResultColumn("quota")
@SingleRowResult
- protected static final String GET_GROUP_QUOTA =
- "SELECT quota FROM user_groups WHERE group_id = :group_id LIMIT 1";
+ protected static final String GET_GROUP_QUOTA = """
+ SELECT quota FROM user_groups
+ WHERE group_id = :group_id
+ LIMIT 1
+ """;
/**
* Get the current non-consolidated usage for a group.
@@ -1134,9 +1313,11 @@ public abstract class SQLQueries {
@Parameter("group_id")
@ResultColumn("current_usage")
@SingleRowResult
- protected static final String GET_CURRENT_USAGE =
- "SELECT COALESCE(SUM(quota_used), 0) AS current_usage"
- + " FROM jobs_usage WHERE group_id = :group_id";
+ protected static final String GET_CURRENT_USAGE = """
+ SELECT COALESCE(SUM(quota_used), 0) AS current_usage
+ FROM jobs_usage
+ WHERE group_id = :group_id
+ """;
/**
* Get usage of a job and the quota against which that applies.
@@ -1147,10 +1328,13 @@ public abstract class SQLQueries {
@ResultColumn("quota_used")
@ResultColumn("quota")
@SingleRowResult
- protected static final String GET_JOB_USAGE_AND_QUOTA =
- "SELECT quota_used, quota FROM jobs_usage "
- + "WHERE job_id = :job_id AND quota_used IS NOT NULL "
- + "AND quota IS NOT NULL LIMIT 1";
+ protected static final String GET_JOB_USAGE_AND_QUOTA = """
+ SELECT quota_used, quota FROM jobs_usage
+ WHERE job_id = :job_id
+ AND quota_used IS NOT NULL
+ AND quota IS NOT NULL
+ LIMIT 1
+ """;
/**
* Get resource usage info about completed jobs that have yet to be
@@ -1161,9 +1345,11 @@ public abstract class SQLQueries {
@ResultColumn("job_id")
@ResultColumn("group_id")
@ResultColumn("quota_used")
- protected static final String GET_CONSOLIDATION_TARGETS =
- "SELECT job_id, group_id, quota_used FROM jobs_usage "
- + "WHERE complete AND quota IS NOT NULL";
+ protected static final String GET_CONSOLIDATION_TARGETS = """
+ SELECT job_id, group_id, quota_used
+ FROM jobs_usage
+ WHERE complete AND quota IS NOT NULL
+ """;
/**
* Reduce a group's quota on a machine by a specified amount.
@@ -1172,9 +1358,11 @@ public abstract class SQLQueries {
*/
@Parameter("usage")
@Parameter("group_id")
- protected static final String DECREMENT_QUOTA =
- "UPDATE user_groups SET quota = quota - :usage "
- + "WHERE group_id = :group_id AND quota IS NOT NULL";
+ protected static final String DECREMENT_QUOTA = """
+ UPDATE user_groups
+ SET quota = quota - :usage
+ WHERE group_id = :group_id AND quota IS NOT NULL
+ """;
/**
* Mark a job as having had its resource usage consolidated.
@@ -1182,8 +1370,11 @@ public abstract class SQLQueries {
* @see QuotaManager
*/
@Parameter("job_id")
- protected static final String MARK_CONSOLIDATED =
- "UPDATE jobs SET accounted_for = 1 WHERE job_id = :job_id";
+ protected static final String MARK_CONSOLIDATED = """
+ UPDATE jobs
+ SET accounted_for = 1
+ WHERE job_id = :job_id
+ """;
/**
* Add or remove time from a quota. Used when someone's administratively
@@ -1193,9 +1384,11 @@ public abstract class SQLQueries {
*/
@Parameter("delta")
@Parameter("group_id")
- protected static final String ADJUST_QUOTA =
- "UPDATE user_groups SET quota = GREATEST(0, quota + :delta) "
- + "WHERE group_id = :group_id AND quota IS NOT NULL";
+ protected static final String ADJUST_QUOTA = """
+ UPDATE user_groups
+ SET quota = GREATEST(0, quota + :delta)
+ WHERE group_id = :group_id AND quota IS NOT NULL
+ """;
/**
* Set a quota. Used when the system is aligning quota with NMPI data.
@@ -1204,9 +1397,12 @@ public abstract class SQLQueries {
*/
@Parameter("new_quota")
@Parameter("group_name")
- protected static final String SET_COLLAB_QUOTA =
- "UPDATE user_groups SET quota = GREATEST(0, :new_quota) "
- + "WHERE group_name = :group_name AND quota IS NOT NULL";
+ protected static final String SET_COLLAB_QUOTA = """
+ UPDATE user_groups
+ SET quota = GREATEST(0, :new_quota)
+ WHERE group_name = :group_name
+ AND quota IS NOT NULL
+ """;
/**
* Get details about a user. This is pretty much everything except their
@@ -1226,13 +1422,16 @@ public abstract class SQLQueries {
@ResultColumn("openid_subject")
@ResultColumn("is_internal")
@SingleRowResult
- protected static final String GET_USER_DETAILS =
- "SELECT user_id, user_name, "
- + "encrypted_password IS NOT NULL AS has_password, "
- + "trust_level, locked, disabled, "
- + "last_successful_login_timestamp, "
- + "last_fail_timestamp, openid_subject, is_internal "
- + "FROM user_info WHERE user_id = :user_id LIMIT 1";
+ protected static final String GET_USER_DETAILS = """
+ SELECT user_id, user_name,
+ encrypted_password IS NOT NULL AS has_password,
+ trust_level, locked, disabled,
+ last_successful_login_timestamp,
+ last_fail_timestamp, openid_subject, is_internal
+ FROM user_info
+ WHERE user_id = :user_id
+ LIMIT 1
+ """;
/**
* Get details about a user. This is pretty much everything except their
@@ -1252,13 +1451,16 @@ public abstract class SQLQueries {
@ResultColumn("openid_subject")
@ResultColumn("is_internal")
@SingleRowResult
- protected static final String GET_USER_DETAILS_BY_NAME =
- "SELECT user_id, user_name, "
- + "encrypted_password IS NOT NULL AS has_password, "
- + "trust_level, locked, disabled, "
- + "last_successful_login_timestamp, "
- + "last_fail_timestamp, openid_subject, is_internal "
- + "FROM user_info WHERE user_name = :user_name LIMIT 1";
+ protected static final String GET_USER_DETAILS_BY_NAME = """
+ SELECT user_id, user_name,
+ encrypted_password IS NOT NULL AS has_password,
+ trust_level, locked, disabled,
+ last_successful_login_timestamp,
+ last_fail_timestamp, openid_subject, is_internal
+ FROM user_info
+ WHERE user_name = :user_name
+ LIMIT 1
+ """;
/**
* Get details about a user. This is pretty much everything except their
@@ -1278,14 +1480,16 @@ public abstract class SQLQueries {
@ResultColumn("openid_subject")
@ResultColumn("is_internal")
@SingleRowResult
- protected static final String GET_USER_DETAILS_BY_SUBJECT =
- "SELECT user_id, user_name, "
- + "encrypted_password IS NOT NULL AS has_password, "
- + "trust_level, locked, disabled, "
- + "last_successful_login_timestamp, "
- + "last_fail_timestamp, openid_subject, is_internal "
- + "FROM user_info WHERE openid_subject = :openid_subject "
- + "LIMIT 1";
+ protected static final String GET_USER_DETAILS_BY_SUBJECT = """
+ SELECT user_id, user_name,
+ encrypted_password IS NOT NULL AS has_password,
+ trust_level, locked, disabled,
+ last_successful_login_timestamp,
+ last_fail_timestamp, openid_subject, is_internal
+ FROM user_info
+ WHERE openid_subject = :openid_subject
+ LIMIT 1
+ """;
/**
* Get a local user's basic details.
@@ -1297,9 +1501,12 @@ public abstract class SQLQueries {
@ResultColumn("user_name")
@ResultColumn("encrypted_password")
@SingleRowResult
- protected static final String GET_LOCAL_USER_DETAILS =
- "SELECT user_id, user_name, encrypted_password FROM user_info "
- + "WHERE user_name = :user_name AND is_internal LIMIT 1";
+ protected static final String GET_LOCAL_USER_DETAILS = """
+ SELECT user_id, user_name, encrypted_password
+ FROM user_info
+ WHERE user_name = :user_name AND is_internal
+ LIMIT 1
+ """;
/**
* Get the ID of a particular group that a particular user must be a member
@@ -1311,12 +1518,15 @@ public abstract class SQLQueries {
@Parameter("group_name")
@ResultColumn("group_id")
@SingleRowResult
- protected static final String GET_GROUP_BY_NAME_AND_MEMBER =
- "SELECT user_groups.group_id FROM user_groups "
- + "JOIN group_memberships USING (group_id) "
- + "JOIN user_info USING (user_id) "
- + "WHERE user_name = :user_name "
- + "AND group_name = :group_name LIMIT 1";
+ protected static final String GET_GROUP_BY_NAME_AND_MEMBER = """
+ SELECT user_groups.group_id
+ FROM user_groups
+ JOIN group_memberships USING (group_id)
+ JOIN user_info USING (user_id)
+ WHERE user_name = :user_name
+ AND group_name = :group_name
+ LIMIT 1
+ """;
/**
* List all the groups that a user is a member of and that have quota left.
@@ -1325,12 +1535,13 @@ public abstract class SQLQueries {
*/
@Parameter("user_name")
@ResultColumn("group_name")
- protected static final String GET_GROUP_NAMES_OF_USER =
- "SELECT user_groups.group_name "
- + "FROM group_memberships "
- + "JOIN user_info USING (user_id) "
- + "JOIN user_groups USING (group_id) "
- + "WHERE user_name = :user_name";
+ protected static final String GET_GROUP_NAMES_OF_USER = """
+ SELECT user_groups.group_name
+ FROM group_memberships
+ JOIN user_info USING (user_id)
+ JOIN user_groups USING (group_id)
+ WHERE user_name = :user_name
+ """;
/**
* List the members of a group.
@@ -1343,13 +1554,15 @@ public abstract class SQLQueries {
@ResultColumn("group_name")
@ResultColumn("user_id")
@ResultColumn("user_name")
- protected static final String GET_USERS_OF_GROUP =
- "SELECT membership_id, user_groups.group_id, "
- + "user_groups.group_name, "
- + "user_info.user_id, user_info.user_name "
- + "FROM group_memberships JOIN user_info USING (user_id) "
- + "JOIN user_groups USING (group_id) "
- + "WHERE group_id = :group_id";
+ protected static final String GET_USERS_OF_GROUP = """
+ SELECT membership_id, user_groups.group_id,
+ user_groups.group_name,
+ user_info.user_id, user_info.user_name
+ FROM group_memberships
+ JOIN user_info USING (user_id)
+ JOIN user_groups USING (group_id)
+ WHERE group_id = :group_id
+ """;
/**
* Get the details from a specific membership.
@@ -1363,12 +1576,14 @@ public abstract class SQLQueries {
@ResultColumn("user_name")
@ResultColumn("group_name")
@SingleRowResult
- protected static final String GET_MEMBERSHIP =
- "SELECT membership_id, user_info.user_id, user_groups.group_id, "
- + "user_name, group_name FROM group_memberships "
- + "JOIN user_info USING (user_id) "
- + "JOIN user_groups USING (group_id) "
- + "WHERE membership_id = :membership_id";
+ protected static final String GET_MEMBERSHIP = """
+ SELECT membership_id, user_info.user_id, user_groups.group_id,
+ user_name, group_name
+ FROM group_memberships
+ JOIN user_info USING (user_id)
+ JOIN user_groups USING (group_id)
+ WHERE membership_id = :membership_id
+ """;
/**
* Get the memberships of a user.
@@ -1381,12 +1596,14 @@ public abstract class SQLQueries {
@ResultColumn("group_id")
@ResultColumn("group_name")
@ResultColumn("user_name")
- protected static final String GET_MEMBERSHIPS_OF_USER =
- "SELECT membership_id, user_info.user_id, user_groups.group_id, "
- + "user_name, group_name FROM group_memberships "
- + "JOIN user_info USING (user_id) "
- + "JOIN user_groups USING (group_id) "
- + "WHERE group_memberships.user_id = :user_id";
+ protected static final String GET_MEMBERSHIPS_OF_USER = """
+ SELECT membership_id, user_info.user_id, user_groups.group_id,
+ user_name, group_name
+ FROM group_memberships
+ JOIN user_info USING (user_id)
+ JOIN user_groups USING (group_id)
+ WHERE group_memberships.user_id = :user_id
+ """;
/**
* Create a group record.
@@ -1397,9 +1614,11 @@ public abstract class SQLQueries {
@Parameter("quota")
@Parameter("group_type")
@GeneratesID
- protected static final String CREATE_GROUP =
- "INSERT INTO user_groups(group_name, quota, group_type) "
- + "VALUES(:group_name, :quota, :group_type)";
+ protected static final String CREATE_GROUP = """
+ INSERT INTO user_groups(
+ group_name, quota, group_type)
+ VALUES(:group_name, :quota, :group_type)
+ """;
/**
* Create a group record.
@@ -1409,9 +1628,11 @@ public abstract class SQLQueries {
@Parameter("group_name")
@Parameter("quota")
@Parameter("group_type")
- protected static final String CREATE_GROUP_IF_NOT_EXISTS =
- "INSERT IGNORE INTO user_groups(group_name, quota, group_type) "
- + "VALUES(:group_name, :quota, :group_type)";
+ protected static final String CREATE_GROUP_IF_NOT_EXISTS = """
+ INSERT IGNORE INTO user_groups(
+ group_name, quota, group_type)
+ VALUES(:group_name, :quota, :group_type)
+ """;
/**
* Delete a single group record and returns the name of the deleted group.
@@ -1421,8 +1642,10 @@ public abstract class SQLQueries {
@Parameter("group_id")
@ResultColumn("group_name")
@SingleRowResult
- protected static final String DELETE_GROUP =
- "DELETE FROM user_groups WHERE group_id = :group_id ";
+ protected static final String DELETE_GROUP = """
+ DELETE FROM user_groups
+ WHERE group_id = :group_id
+ """;
/**
* Update a single group record's name and quota.
@@ -1433,9 +1656,12 @@ public abstract class SQLQueries {
@Parameter("quota")
@Parameter("group_id")
@SingleRowResult
- protected static final String UPDATE_GROUP = "UPDATE user_groups SET "
- + "group_name = COALESCE(:group_name, group_name), "
- + "quota = :quota WHERE group_id = :group_id ";
+ protected static final String UPDATE_GROUP = """
+ UPDATE user_groups
+ SET group_name = COALESCE(:group_name, group_name),
+ quota = :quota
+ WHERE group_id = :group_id
+ """;
/**
* Adds a user to a group.
@@ -1445,10 +1671,12 @@ public abstract class SQLQueries {
@Parameter("user_id")
@Parameter("group_id")
@GeneratesID
- protected static final String ADD_USER_TO_GROUP =
- "INSERT INTO group_memberships(user_id, group_id) "
- + "VALUES (:user_id, :group_id) "
- + "ON DUPLICATE KEY UPDATE user_id=user_id;";
+ protected static final String ADD_USER_TO_GROUP = """
+ INSERT INTO group_memberships(
+ user_id, group_id)
+ VALUES (:user_id, :group_id)
+ ON DUPLICATE KEY UPDATE user_id = user_id
+ """;
/**
* Removes a user from a group.
@@ -1457,9 +1685,10 @@ public abstract class SQLQueries {
*/
@Parameter("user_id")
@Parameter("group_id")
- protected static final String REMOVE_USER_FROM_GROUP =
- "DELETE FROM group_memberships "
- + "WHERE user_id = :user_id AND group_id = :group_id";
+ protected static final String REMOVE_USER_FROM_GROUP = """
+ DELETE FROM group_memberships
+ WHERE user_id = :user_id AND group_id = :group_id
+ """;
/**
* Step 1 of group synchronisation: make a temporary table. Should be
@@ -1467,8 +1696,10 @@ public abstract class SQLQueries {
*
* @see LocalAuthProviderImpl
*/
- protected static final String GROUP_SYNC_MAKE_TEMP_TABLE =
- "CREATE TEMPORARY TABLE usergroupids(group_id INTEGER)";
+ protected static final String GROUP_SYNC_MAKE_TEMP_TABLE = """
+ CREATE TEMPORARY TABLE usergroupids(
+ group_id INTEGER)
+ """;
/**
* Step 2 of group synchronisation: add a desired group to the temp table.
@@ -1480,10 +1711,12 @@ public abstract class SQLQueries {
*/
@Parameter("group_name")
@Parameter("group_type")
- protected static final String GROUP_SYNC_INSERT_TEMP_ROW =
- "INSERT INTO usergroupids SELECT group_id FROM user_groups "
- + "WHERE group_name = :group_name "
- + "AND group_type = :group_type";
+ protected static final String GROUP_SYNC_INSERT_TEMP_ROW = """
+ INSERT INTO usergroupids
+ SELECT group_id FROM user_groups
+ WHERE group_name = :group_name
+ AND group_type = :group_type
+ """;
/**
* Step 3 of group synchronisation: add real missing groups. Requires the
@@ -1495,10 +1728,12 @@ public abstract class SQLQueries {
* @see LocalAuthProviderImpl
*/
@Parameter("user_id")
- protected static final String GROUP_SYNC_ADD_GROUPS =
- "INSERT IGNORE INTO group_memberships(user_id, group_id) "
- + "SELECT :user_id AS user_id, "
- + "group_id FROM usergroupids";
+ protected static final String GROUP_SYNC_ADD_GROUPS = """
+ INSERT IGNORE INTO group_memberships(
+ user_id, group_id)
+ SELECT :user_id AS user_id, group_id
+ FROM usergroupids
+ """;
/**
* Step 4 of group synchronisation: remove real groups no longer wanted.
@@ -1510,23 +1745,22 @@ public abstract class SQLQueries {
* @see LocalAuthProviderImpl
*/
@Parameter("user_id")
- protected static final String GROUP_SYNC_REMOVE_GROUPS =
- "DELETE FROM group_memberships "
- + "WHERE user_id = :user_id AND group_id NOT IN ("
- + "SELECT group_id FROM usergroupids)";
+ protected static final String GROUP_SYNC_REMOVE_GROUPS = """
+ DELETE FROM group_memberships
+ WHERE user_id = :user_id AND group_id NOT IN (
+ SELECT group_id FROM usergroupids)
+ """;
/**
- * Step 5 of group synchronisation: drop the temporary table. Except we
- * don't because that doesn't work in a transaction; squelching the contents
- * works though (the table itself is dropped automatically when the
- * connection is dropped so we don't need to clean it up here). Should be
+ * Step 5 of group synchronisation: drop the temporary table. Should be
* performed in a transaction with the other group synch steps. Requires
* that {@link #GROUP_SYNC_MAKE_TEMP_TABLE} was run first.
*
* @see LocalAuthProviderImpl
*/
- protected static final String GROUP_SYNC_DROP_TEMP_TABLE =
- "DROP TEMPORARY TABLE usergroupids";
+ protected static final String GROUP_SYNC_DROP_TEMP_TABLE = """
+ DROP TEMPORARY TABLE usergroupids
+ """;
/**
* Test if a user account is locked or disabled.
@@ -1538,9 +1772,12 @@ public abstract class SQLQueries {
@ResultColumn("locked")
@ResultColumn("disabled")
@SingleRowResult
- protected static final String IS_USER_LOCKED =
- "SELECT user_id, locked, disabled FROM user_info "
- + "WHERE user_name = :username";
+ protected static final String IS_USER_LOCKED = """
+ SELECT user_id, locked, disabled
+ FROM user_info
+ WHERE user_name = :username
+ LIMIT 1
+ """;
/**
* Get the permissions and encrypted password for a user.
@@ -1552,9 +1789,12 @@ public abstract class SQLQueries {
@ResultColumn("encrypted_password")
@ResultColumn("openid_subject")
@SingleRowResult
- protected static final String GET_USER_AUTHORITIES =
- "SELECT trust_level, encrypted_password, openid_subject "
- + "FROM user_info WHERE user_id = :user_id LIMIT 1";
+ protected static final String GET_USER_AUTHORITIES = """
+ SELECT trust_level, encrypted_password, openid_subject
+ FROM user_info
+ WHERE user_id = :user_id
+ LIMIT 1
+ """;
/**
* Note the login success.
@@ -1563,10 +1803,12 @@ public abstract class SQLQueries {
*/
@Parameter("openid_subject")
@Parameter("user_id")
- protected static final String MARK_LOGIN_SUCCESS = "UPDATE user_info SET "
- + "last_successful_login_timestamp = UNIX_TIMESTAMP(), "
- + "failure_count = 0, openid_subject = :openid_subject "
- + "WHERE user_id = :user_id";
+ protected static final String MARK_LOGIN_SUCCESS = """
+ UPDATE user_info
+ SET last_successful_login_timestamp = UNIX_TIMESTAMP(),
+ failure_count = 0, openid_subject = :openid_subject
+ WHERE user_id = :user_id
+ """;
/**
* Note the login failure.
@@ -1575,11 +1817,13 @@ public abstract class SQLQueries {
*/
@Parameter("failure_limit")
@Parameter("user_id")
- protected static final String MARK_LOGIN_FAILURE =
- "UPDATE user_info SET failure_count = failure_count + 1, "
- + "last_fail_timestamp = UNIX_TIMESTAMP(), "
- + "locked = (failure_count + 1 >= :failure_limit) "
- + "WHERE user_id = :user_id";
+ protected static final String MARK_LOGIN_FAILURE = """
+ UPDATE user_info
+ SET failure_count = failure_count + 1,
+ last_fail_timestamp = UNIX_TIMESTAMP(),
+ locked = (failure_count + 1 >= :failure_limit)
+ WHERE user_id = :user_id
+ """;
/**
* Unlock accounts.
@@ -1587,11 +1831,12 @@ public abstract class SQLQueries {
* @see LocalAuthProviderImpl
*/
@Parameter("lock_interval")
- protected static final String UNLOCK_LOCKED_USERS =
- "UPDATE user_info SET failure_count = 0, last_fail_timestamp = 0, "
- + "locked = 0 WHERE last_fail_timestamp + :lock_interval "
- + "< UNIX_TIMESTAMP() "
- + "AND locked";
+ protected static final String UNLOCK_LOCKED_USERS = """
+ UPDATE user_info
+ SET failure_count = 0, last_fail_timestamp = 0, locked = 0
+ WHERE last_fail_timestamp + :lock_interval < UNIX_TIMESTAMP()
+ AND locked
+ """;
/**
* Delete a user.
@@ -1599,8 +1844,10 @@ public abstract class SQLQueries {
* @see UserControl
*/
@Parameter("user_id")
- protected static final String DELETE_USER =
- "DELETE FROM user_info WHERE user_id = :user_id";
+ protected static final String DELETE_USER = """
+ DELETE FROM user_info
+ WHERE user_id = :user_id
+ """;
/**
* Get the ID of a user. Used for safety checks.
@@ -1611,8 +1858,12 @@ public abstract class SQLQueries {
@Parameter("user_name")
@ResultColumn("user_id")
@SingleRowResult
- protected static final String GET_USER_ID = "SELECT user_id FROM user_info "
- + "WHERE user_name = :user_name LIMIT 1";
+ protected static final String GET_USER_ID = """
+ SELECT user_id
+ FROM user_info
+ WHERE user_name = :user_name
+ LIMIT 1
+ """;
/**
* Set the amount a user is trusted.
@@ -1621,9 +1872,11 @@ public abstract class SQLQueries {
*/
@Parameter("trust")
@Parameter("user_id")
- protected static final String SET_USER_TRUST =
- "UPDATE user_info SET trust_level = :trust "
- + "WHERE user_id = :user_id";
+ protected static final String SET_USER_TRUST = """
+ UPDATE user_info
+ SET trust_level = :trust
+ WHERE user_id = :user_id
+ """;
/**
* Set whether a user is locked. Can be used to unlock a user early.
@@ -1632,8 +1885,11 @@ public abstract class SQLQueries {
*/
@Parameter("locked")
@Parameter("user_id")
- protected static final String SET_USER_LOCKED =
- "UPDATE user_info SET locked = :locked WHERE user_id = :user_id";
+ protected static final String SET_USER_LOCKED = """
+ UPDATE user_info
+ SET locked = :locked
+ WHERE user_id = :user_id
+ """;
/**
* Set whether a user is administratively disabled.
@@ -1642,9 +1898,11 @@ public abstract class SQLQueries {
*/
@Parameter("disabled")
@Parameter("user_id")
- protected static final String SET_USER_DISABLED =
- "UPDATE user_info SET disabled = :disabled "
- + "WHERE user_id = :user_id";
+ protected static final String SET_USER_DISABLED = """
+ UPDATE user_info
+ SET disabled = :disabled
+ WHERE user_id = :user_id
+ """;
/**
* Set a user's password. Passwords are either encrypted (with bcrypt) or
@@ -1655,9 +1913,11 @@ public abstract class SQLQueries {
*/
@Parameter("password")
@Parameter("user_id")
- protected static final String SET_USER_PASS =
- "UPDATE user_info SET encrypted_password = :password "
- + "WHERE user_id = :user_id";
+ protected static final String SET_USER_PASS = """
+ UPDATE user_info
+ SET encrypted_password = :password
+ WHERE user_id = :user_id
+ """;
/**
* Set a user's name.
@@ -1666,9 +1926,11 @@ public abstract class SQLQueries {
*/
@Parameter("user_name")
@Parameter("user_id")
- protected static final String SET_USER_NAME =
- "UPDATE user_info SET user_name = :user_name "
- + "WHERE user_id = :user_id";
+ protected static final String SET_USER_NAME = """
+ UPDATE user_info
+ SET user_name = :user_name
+ WHERE user_id = :user_id
+ """;
/**
* Get a list of all users.
@@ -1678,8 +1940,10 @@ public abstract class SQLQueries {
@ResultColumn("user_id")
@ResultColumn("user_name")
@ResultColumn("openid_subject")
- protected static final String LIST_ALL_USERS =
- "SELECT user_id, user_name, openid_subject FROM user_info";
+ protected static final String LIST_ALL_USERS = """
+ SELECT user_id, user_name, openid_subject
+ FROM user_info
+ """;
/**
* Get a list of all users.
@@ -1690,9 +1954,11 @@ public abstract class SQLQueries {
@ResultColumn("user_id")
@ResultColumn("user_name")
@ResultColumn("openid_subject")
- protected static final String LIST_ALL_USERS_OF_TYPE =
- "SELECT user_id, user_name, openid_subject FROM user_info "
- + "WHERE is_internal = :internal";
+ protected static final String LIST_ALL_USERS_OF_TYPE = """
+ SELECT user_id, user_name, openid_subject
+ FROM user_info
+ WHERE is_internal = :internal
+ """;
/**
* Create a user. Passwords are either encrypted (with bcrypt) or
@@ -1707,11 +1973,13 @@ public abstract class SQLQueries {
@Parameter("disabled")
@Parameter("openid_subject")
@GeneratesID
- protected static final String CREATE_USER =
- "INSERT IGNORE INTO user_info(user_name, encrypted_password, "
- + "trust_level, disabled, openid_subject) "
- + "VALUES(:user_name, :encoded_password, :trust_level, "
- + ":disabled, :openid_subject)";
+ protected static final String CREATE_USER = """
+ INSERT IGNORE INTO user_info(
+ user_name, encrypted_password, trust_level, disabled,
+ openid_subject)
+ VALUES(:user_name, :encoded_password, :trust_level, :disabled,
+ :openid_subject)
+ """;
/**
* Get a list of all groups.
@@ -1722,8 +1990,10 @@ public abstract class SQLQueries {
@ResultColumn("group_name")
@ResultColumn("quota")
@ResultColumn("group_type")
- protected static final String LIST_ALL_GROUPS =
- "SELECT group_id, group_name, quota, group_type FROM user_groups";
+ protected static final String LIST_ALL_GROUPS = """
+ SELECT group_id, group_name, quota, group_type
+ FROM user_groups
+ """;
/**
* Get a list of all groups of a given type.
@@ -1735,9 +2005,11 @@ public abstract class SQLQueries {
@ResultColumn("group_name")
@ResultColumn("quota")
@ResultColumn("group_type")
- protected static final String LIST_ALL_GROUPS_OF_TYPE =
- "SELECT group_id, group_name, quota, group_type FROM user_groups "
- + "WHERE group_type = :type";
+ protected static final String LIST_ALL_GROUPS_OF_TYPE = """
+ SELECT group_id, group_name, quota, group_type
+ FROM user_groups
+ WHERE group_type = :type
+ """;
/**
* Get a group by it's ID.
@@ -1750,9 +2022,12 @@ public abstract class SQLQueries {
@ResultColumn("quota")
@ResultColumn("group_type")
@SingleRowResult
- protected static final String GET_GROUP_BY_ID =
- "SELECT group_id, group_name, quota, group_type FROM user_groups "
- + "WHERE group_id = :group_id LIMIT 1";
+ protected static final String GET_GROUP_BY_ID = """
+ SELECT group_id, group_name, quota, group_type
+ FROM user_groups
+ WHERE group_id = :group_id
+ LIMIT 1
+ """;
/**
* Get a group by it's name.
@@ -1765,9 +2040,12 @@ public abstract class SQLQueries {
@ResultColumn("quota")
@ResultColumn("group_type")
@SingleRowResult
- protected static final String GET_GROUP_BY_NAME =
- "SELECT group_id, group_name, quota, group_type FROM user_groups "
- + "WHERE group_name = :group_name LIMIT 1";
+ protected static final String GET_GROUP_BY_NAME = """
+ SELECT group_id, group_name, quota, group_type
+ FROM user_groups
+ WHERE group_name = :group_name
+ LIMIT 1
+ """;
/**
* Create a board issue report.
@@ -1779,12 +2057,11 @@ public abstract class SQLQueries {
@Parameter("issue")
@Parameter("user_id")
@GeneratesID
- protected static final String INSERT_BOARD_REPORT =
- "INSERT INTO board_reports("
- + "board_id, job_id, reported_issue, reporter, "
- + "report_timestamp) "
- + "VALUES(:board_id, :job_id, :issue, :user_id, "
- + "UNIX_TIMESTAMP())";
+ protected static final String INSERT_BOARD_REPORT = """
+ INSERT INTO board_reports(
+ board_id, job_id, reported_issue, reporter, report_timestamp)
+ VALUES(:board_id, :job_id, :issue, :user_id, UNIX_TIMESTAMP())
+ """;
/**
* Actually delete a job record. Only called by the data tombstone-r. This
@@ -1793,8 +2070,10 @@ public abstract class SQLQueries {
* @see AllocatorTask#tombstone()
*/
@Parameter("job_id")
- protected static final String DELETE_JOB_RECORD =
- "DELETE FROM jobs WHERE job_id = :job_id";
+ protected static final String DELETE_JOB_RECORD = """
+ DELETE FROM jobs
+ WHERE job_id = :job_id
+ """;
/**
* Actually delete an allocation record. Only called by the data
@@ -1804,8 +2083,10 @@ public abstract class SQLQueries {
* @see AllocatorTask#tombstone()
*/
@Parameter("alloc_id")
- protected static final String DELETE_ALLOC_RECORD =
- "DELETE FROM old_board_allocations WHERE alloc_id = :alloc_id";
+ protected static final String DELETE_ALLOC_RECORD = """
+ DELETE FROM old_board_allocations
+ WHERE alloc_id = :alloc_id
+ """;
/**
* Read the blacklisted chips for a board.
@@ -1816,10 +2097,12 @@ public abstract class SQLQueries {
@ResultColumn("x")
@ResultColumn("y")
@ResultColumn("notes")
- protected static final String GET_BLACKLISTED_CHIPS =
- "SELECT chip_x AS x, chip_y AS y, notes FROM blacklisted_chips "
- + "JOIN board_model_coords USING (coord_id) "
- + "WHERE board_id = :board_id";
+ protected static final String GET_BLACKLISTED_CHIPS = """
+ SELECT chip_x AS x, chip_y AS y, notes
+ FROM blacklisted_chips
+ JOIN board_model_coords USING (coord_id)
+ WHERE board_id = :board_id
+ """;
/**
* Read the blacklisted cores for a board.
@@ -1831,11 +2114,12 @@ public abstract class SQLQueries {
@ResultColumn("y")
@ResultColumn("p")
@ResultColumn("notes")
- protected static final String GET_BLACKLISTED_CORES =
- "SELECT chip_x AS x, chip_y AS y, physical_core AS p, notes "
- + "FROM blacklisted_cores "
- + "JOIN board_model_coords USING (coord_id) "
- + "WHERE board_id = :board_id";
+ protected static final String GET_BLACKLISTED_CORES = """
+ SELECT chip_x AS x, chip_y AS y, physical_core AS p, notes
+ FROM blacklisted_cores
+ JOIN board_model_coords USING (coord_id)
+ WHERE board_id = :board_id
+ """;
/**
* Read the blacklisted links for a board.
@@ -1847,11 +2131,12 @@ public abstract class SQLQueries {
@ResultColumn("y")
@ResultColumn("direction")
@ResultColumn("notes")
- protected static final String GET_BLACKLISTED_LINKS =
- "SELECT chip_x AS x, chip_y AS y, direction, notes "
- + "FROM blacklisted_links "
- + "JOIN board_model_coords USING (coord_id) "
- + "WHERE board_id = :board_id";
+ protected static final String GET_BLACKLISTED_LINKS = """
+ SELECT chip_x AS x, chip_y AS y, direction, notes
+ FROM blacklisted_links
+ JOIN board_model_coords USING (coord_id)
+ WHERE board_id = :board_id
+ """;
/**
* Mark a board as having had its blacklist modified.
@@ -1859,9 +2144,11 @@ public abstract class SQLQueries {
* @see MachineStateControl
*/
@Parameter("board_id")
- protected static final String MARK_BOARD_BLACKLIST_CHANGED =
- "UPDATE boards SET blacklist_set_timestamp = UNIX_TIMESTAMP() "
- + "WHERE board_id = :board_id";
+ protected static final String MARK_BOARD_BLACKLIST_CHANGED = """
+ UPDATE boards
+ SET blacklist_set_timestamp = UNIX_TIMESTAMP()
+ WHERE board_id = :board_id
+ """;
/**
* Mark a board as having had its blacklist synchronised with the hardware.
@@ -1869,9 +2156,11 @@ public abstract class SQLQueries {
* @see MachineStateControl
*/
@Parameter("board_id")
- protected static final String MARK_BOARD_BLACKLIST_SYNCHED =
- "UPDATE boards SET blacklist_sync_timestamp = UNIX_TIMESTAMP() "
- + "WHERE board_id = :board_id";
+ protected static final String MARK_BOARD_BLACKLIST_SYNCHED = """
+ UPDATE boards
+ SET blacklist_sync_timestamp = UNIX_TIMESTAMP()
+ WHERE board_id = :board_id
+ """;
/**
* Asks whether the blacklist model for a board is believed to be
@@ -1882,10 +2171,13 @@ public abstract class SQLQueries {
@Parameter("board_id")
@ResultColumn("current")
@SingleRowResult
- protected static final String IS_BOARD_BLACKLIST_CURRENT =
- "SELECT blacklist_sync_timestamp >= blacklist_set_timestamp "
- + "AS current FROM boards WHERE board_id = :board_id "
- + "LIMIT 1";
+ protected static final String IS_BOARD_BLACKLIST_CURRENT = """
+ SELECT blacklist_sync_timestamp >= blacklist_set_timestamp
+ AS current
+ FROM boards
+ WHERE board_id = :board_id
+ LIMIT 1
+ """;
/**
* Add a chip on a board to that board's blacklist. Does not cause the
@@ -1897,15 +2189,18 @@ public abstract class SQLQueries {
@Parameter("board_id")
@Parameter("x")
@Parameter("y")
- protected static final String ADD_BLACKLISTED_CHIP =
- "INSERT INTO blacklisted_chips(board_id, coord_id, notes) "
- + "WITH args(board_id, x, y) AS (SELECT :board_id, :x, :y),"
- + "m(model) AS (SELECT board_model FROM machines "
- + "JOIN boards USING (machine_id) "
- + "JOIN args USING (board_id)) "
- + "SELECT args.board_id, coord_id, NULL "
- + "FROM board_model_coords JOIN m USING (model) JOIN args "
- + "WHERE chip_x = args.x AND chip_y = args.y";
+ protected static final String ADD_BLACKLISTED_CHIP = """
+ INSERT INTO blacklisted_chips(board_id, coord_id, notes)
+ WITH args(board_id, x, y) AS (SELECT :board_id, :x, :y),
+ m(model) AS (SELECT board_model FROM machines
+ JOIN boards USING (machine_id)
+ JOIN args USING (board_id))
+ SELECT args.board_id, coord_id, NULL
+ FROM board_model_coords
+ JOIN m USING (model)
+ JOIN args
+ WHERE chip_x = args.x AND chip_y = args.y
+ """;
/**
* Add a core on a board to that board's blacklist. Does not cause the
@@ -1918,17 +2213,19 @@ public abstract class SQLQueries {
@Parameter("x")
@Parameter("y")
@Parameter("p")
- protected static final String ADD_BLACKLISTED_CORE =
- "INSERT INTO blacklisted_cores("
- + "board_id, coord_id, physical_core, notes) "
- + "WITH args(board_id, x, y, p) AS "
- + "(SELECT :board_id, :x, :y, :p), "
- + "m(model) AS (SELECT board_model FROM machines "
- + "JOIN boards USING (machine_id) "
- + "JOIN args USING (board_id)) "
- + "SELECT args.board_id, coord_id, p, NULL "
- + "FROM board_model_coords JOIN m USING (model) JOIN args "
- + "WHERE chip_x = args.x AND chip_y = args.y";
+ protected static final String ADD_BLACKLISTED_CORE = """
+ INSERT INTO blacklisted_cores(
+ board_id, coord_id, physical_core, notes)
+ WITH args(board_id, x, y, p) AS (SELECT :board_id, :x, :y, :p),
+ m(model) AS (SELECT board_model FROM machines
+ JOIN boards USING (machine_id)
+ JOIN args USING (board_id))
+ SELECT args.board_id, coord_id, p, NULL
+ FROM board_model_coords
+ JOIN m USING (model)
+ JOIN args
+ WHERE chip_x = args.x AND chip_y = args.y
+ """;
/**
* Add a link on a board to that board's blacklist. Does not cause the
@@ -1941,17 +2238,20 @@ public abstract class SQLQueries {
@Parameter("x")
@Parameter("y")
@Parameter("direction")
- protected static final String ADD_BLACKLISTED_LINK =
- "INSERT INTO blacklisted_links("
- + "board_id, coord_id, direction, notes) "
- + "WITH args(board_id, x, y, dir) AS ("
- + "SELECT :board_id, :x, :y, :direction), "
- + "m(model) AS (SELECT board_model FROM machines "
- + "JOIN boards USING (machine_id) "
- + "JOIN args USING (board_id)) "
- + "SELECT args.board_id, coord_id, dir, NULL "
- + "FROM board_model_coords JOIN m USING (model) JOIN args "
- + "WHERE chip_x = args.x AND chip_y = args.y";
+ protected static final String ADD_BLACKLISTED_LINK = """
+ INSERT INTO blacklisted_links(
+ board_id, coord_id, direction, notes)
+ WITH args(board_id, x, y, dir) AS (
+ SELECT :board_id, :x, :y, :direction),
+ m(model) AS (SELECT board_model FROM machines
+ JOIN boards USING (machine_id)
+ JOIN args USING (board_id))
+ SELECT args.board_id, coord_id, dir, NULL
+ FROM board_model_coords
+ JOIN m USING (model)
+ JOIN args
+ WHERE chip_x = args.x AND chip_y = args.y
+ """;
/**
* Delete all blacklist entries for chips on a board.
@@ -1959,8 +2259,10 @@ public abstract class SQLQueries {
* @see BlacklistStore
*/
@Parameter("board_id")
- protected static final String CLEAR_BLACKLISTED_CHIPS =
- "DELETE FROM blacklisted_chips WHERE board_id = :board_id";
+ protected static final String CLEAR_BLACKLISTED_CHIPS = """
+ DELETE FROM blacklisted_chips
+ WHERE board_id = :board_id
+ """;
/**
* Delete all blacklist entries for cores on a board.
@@ -1968,8 +2270,10 @@ public abstract class SQLQueries {
* @see BlacklistStore
*/
@Parameter("board_id")
- protected static final String CLEAR_BLACKLISTED_CORES =
- "DELETE FROM blacklisted_cores WHERE board_id = :board_id";
+ protected static final String CLEAR_BLACKLISTED_CORES = """
+ DELETE FROM blacklisted_cores
+ WHERE board_id = :board_id
+ """;
/**
* Delete all blacklist entries for links on a board.
@@ -1977,8 +2281,10 @@ public abstract class SQLQueries {
* @see BlacklistStore
*/
@Parameter("board_id")
- protected static final String CLEAR_BLACKLISTED_LINKS =
- "DELETE FROM blacklisted_links WHERE board_id = :board_id";
+ protected static final String CLEAR_BLACKLISTED_LINKS = """
+ DELETE FROM blacklisted_links
+ WHERE board_id = :board_id
+ """;
/**
* Get the list of writes (to the machine) of blacklist data to perform.
@@ -1993,14 +2299,17 @@ public abstract class SQLQueries {
@ResultColumn("cabinet")
@ResultColumn("frame")
@ResultColumn("machine_id")
- protected static final String GET_BLACKLIST_WRITES =
- "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, "
- + "cabinet, frame, data, boards.machine_id "
- + "FROM blacklist_ops "
- + "JOIN boards USING (board_id) JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE op = 1 AND NOT completed "
- + "AND boards.bmp_id = :bmp_id";
+ protected static final String GET_BLACKLIST_WRITES = """
+ SELECT op_id, board_id, board_serial.bmp_serial_id, board_num,
+ cabinet, frame, data, boards.machine_id
+ FROM blacklist_ops
+ JOIN boards USING (board_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE op = 1
+ AND NOT completed
+ AND boards.bmp_id = :bmp_id
+ """;
/**
* Get the list of reads (from the machine) of blacklist data to perform.
@@ -2015,13 +2324,17 @@ public abstract class SQLQueries {
@ResultColumn("cabinet")
@ResultColumn("frame")
@ResultColumn("machine_id")
- protected static final String GET_BLACKLIST_READS =
- "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, "
- + "cabinet, frame, boards.machine_id FROM blacklist_ops "
- + "JOIN boards USING (board_id) JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE op = 0 AND NOT completed "
- + "AND boards.bmp_id = :bmp_id";
+ protected static final String GET_BLACKLIST_READS = """
+ SELECT op_id, board_id, board_serial.bmp_serial_id, board_num,
+ cabinet, frame, boards.machine_id
+ FROM blacklist_ops
+ JOIN boards USING (board_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE op = 0
+ AND NOT completed
+ AND boards.bmp_id = :bmp_id
+ """;
/**
* Get the list of reads (from the machine) of serial data to perform.
@@ -2036,13 +2349,17 @@ public abstract class SQLQueries {
@ResultColumn("cabinet")
@ResultColumn("frame")
@ResultColumn("machine_id")
- protected static final String GET_SERIAL_INFO_REQS =
- "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, "
- + "cabinet, frame, boards.machine_id FROM blacklist_ops "
- + "JOIN boards USING (board_id) JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE op = 2 AND NOT completed "
- + "AND boards.bmp_id = :bmp_id";
+ protected static final String GET_SERIAL_INFO_REQS = """
+ SELECT op_id, board_id, board_serial.bmp_serial_id, board_num,
+ cabinet, frame, boards.machine_id
+ FROM blacklist_ops
+ JOIN boards USING (board_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE op = 2
+ AND NOT completed
+ AND boards.bmp_id = :bmp_id
+ """;
/**
* Get the list of reads (from the machine) of temperature data to perform.
@@ -2057,13 +2374,17 @@ public abstract class SQLQueries {
@ResultColumn("cabinet")
@ResultColumn("frame")
@ResultColumn("machine_id")
- protected static final String GET_TEMP_INFO_REQS =
- "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, "
- + "cabinet, frame, boards.machine_id FROM blacklist_ops "
- + "JOIN boards USING (board_id) JOIN bmp USING (bmp_id) "
- + "LEFT JOIN board_serial USING (board_id) "
- + "WHERE op = 3 AND NOT completed "
- + "AND boards.machine_id = :machine_id";
+ protected static final String GET_TEMP_INFO_REQS = """
+ SELECT op_id, board_id, board_serial.bmp_serial_id, board_num,
+ cabinet, frame, boards.machine_id
+ FROM blacklist_ops
+ JOIN boards USING (board_id)
+ JOIN bmp USING (bmp_id)
+ LEFT JOIN board_serial USING (board_id)
+ WHERE op = 3
+ AND NOT completed
+ AND boards.machine_id = :machine_id
+ """;
/**
* Set the BMP and physical serial IDs based on the information actually
@@ -2076,13 +2397,14 @@ public abstract class SQLQueries {
@Parameter("bmp_serial_id")
@Parameter("physical_serial_id")
@GeneratesID
- protected static final String SET_BOARD_SERIAL_IDS =
- "INSERT INTO board_serial("
- + "board_id, bmp_serial_id, physical_serial_id) "
- + "VALUES(:board_id, :bmp_serial_id, :physical_serial_id) "
- + "ON DUPLICATE KEY UPDATE "
- + "bmp_serial_id = VALUES(bmp_serial_id), "
- + "physical_serial_id = VALUES(physical_serial_id)";
+ protected static final String SET_BOARD_SERIAL_IDS = """
+ INSERT INTO board_serial(
+ board_id, bmp_serial_id, physical_serial_id)
+ VALUES(:board_id, :bmp_serial_id, :physical_serial_id)
+ ON DUPLICATE KEY UPDATE
+ bmp_serial_id = VALUES(bmp_serial_id),
+ physical_serial_id = VALUES(physical_serial_id)
+ """;
/**
* Mark a read of a blacklist or ADC data as completed.
@@ -2091,9 +2413,11 @@ public abstract class SQLQueries {
*/
@Parameter("data")
@Parameter("op_id")
- protected static final String COMPLETED_BOARD_INFO_READ =
- "UPDATE blacklist_ops SET data = :data, completed = 1 "
- + "WHERE op_id = :op_id";
+ protected static final String COMPLETED_BOARD_INFO_READ = """
+ UPDATE blacklist_ops
+ SET data = :data, completed = 1
+ WHERE op_id = :op_id
+ """;
/**
* Mark a write of a blacklist as completed.
@@ -2101,8 +2425,11 @@ public abstract class SQLQueries {
* @see BMPController
*/
@Parameter("op_id")
- protected static final String COMPLETED_BLACKLIST_WRITE =
- "UPDATE blacklist_ops SET completed = 1 WHERE op_id = :op_id";
+ protected static final String COMPLETED_BLACKLIST_WRITE = """
+ UPDATE blacklist_ops
+ SET completed = 1
+ WHERE op_id = :op_id
+ """;
/**
* Mark a read of serial data as completed. (Text same as
@@ -2111,8 +2438,11 @@ public abstract class SQLQueries {
* @see BMPController
*/
@Parameter("op_id")
- protected static final String COMPLETED_GET_SERIAL_REQ =
- "UPDATE blacklist_ops SET completed = 1 WHERE op_id = :op_id";
+ protected static final String COMPLETED_GET_SERIAL_REQ = """
+ UPDATE blacklist_ops
+ SET completed = 1
+ WHERE op_id = :op_id
+ """;
/**
* Mark a read or write of a blacklist as failed, noting the reason.
@@ -2121,8 +2451,11 @@ public abstract class SQLQueries {
*/
@Parameter("failure")
@Parameter("op_id")
- protected static final String FAILED_BLACKLIST_OP = "UPDATE blacklist_ops "
- + "SET failure = :failure, completed = 1 WHERE op_id = :op_id";
+ protected static final String FAILED_BLACKLIST_OP = """
+ UPDATE blacklist_ops
+ SET failure = :failure, completed = 1
+ WHERE op_id = :op_id
+ """;
/**
* Retrieve a completed request to read or write a BMP-related data for a
@@ -2136,11 +2469,12 @@ public abstract class SQLQueries {
@ResultColumn("data")
@ResultColumn("failure")
@SingleRowResult
- protected static final String GET_COMPLETED_BLACKLIST_OP =
- "SELECT board_id, op, data, failure, "
- + "failure IS NOT NULL AS failed "
- + "FROM blacklist_ops WHERE op_id = :op_id AND completed "
- + "LIMIT 1";
+ protected static final String GET_COMPLETED_BLACKLIST_OP = """
+ SELECT board_id, op, data, failure, failure IS NOT NULL AS failed
+ FROM blacklist_ops
+ WHERE op_id = :op_id AND completed
+ LIMIT 1
+ """;
/**
* Delete a blacklist request.
@@ -2148,8 +2482,10 @@ public abstract class SQLQueries {
* @see MachineStateControl
*/
@Parameter("op_id")
- protected static final String DELETE_BLACKLIST_OP =
- "DELETE FROM blacklist_ops WHERE op_id = :op_id";
+ protected static final String DELETE_BLACKLIST_OP = """
+ DELETE FROM blacklist_ops
+ WHERE op_id = :op_id
+ """;
/**
* Insert a request to read a board's blacklist.
@@ -2158,9 +2494,11 @@ public abstract class SQLQueries {
*/
@Parameter("board_id")
@GeneratesID
- protected static final String CREATE_BLACKLIST_READ =
- "INSERT INTO blacklist_ops(board_id, op, completed) "
- + "VALUES(:board_id, 0, 0)";
+ protected static final String CREATE_BLACKLIST_READ = """
+ INSERT INTO blacklist_ops(
+ board_id, op, completed)
+ VALUES (:board_id, 0, 0)
+ """;
/**
* Insert a request to write a board's blacklist.
@@ -2170,9 +2508,11 @@ public abstract class SQLQueries {
@Parameter("board_id")
@Parameter("blacklist")
@GeneratesID
- protected static final String CREATE_BLACKLIST_WRITE =
- "INSERT INTO blacklist_ops(board_id, op, completed, data) "
- + "VALUES(:board_id, 1, 0, :blacklist)";
+ protected static final String CREATE_BLACKLIST_WRITE = """
+ INSERT INTO blacklist_ops(
+ board_id, op, completed, data)
+ VALUES (:board_id, 1, 0, :blacklist)
+ """;
/**
* Insert a request to read a board's serial information.
@@ -2181,9 +2521,231 @@ public abstract class SQLQueries {
*/
@Parameter("board_id")
@GeneratesID
- protected static final String CREATE_SERIAL_READ_REQ =
- "INSERT INTO blacklist_ops(board_id, op, completed) "
- + "VALUES(:board_id, 2, 0)";
+ protected static final String CREATE_SERIAL_READ_REQ = """
+ INSERT INTO blacklist_ops(
+ board_id, op, completed)
+ VALUES (:board_id, 2, 0)
+ """;
+
+ /**
+ * Find an allocatable board with a specific board ID. (This will have been
+ * previously converted from some other form of board coordinates.)
+ *
+ * @see AllocatorTask
+ */
+ @Parameter("machine_id")
+ @Parameter("board_id")
+ @ResultColumn("x")
+ @ResultColumn("y")
+ @ResultColumn("z")
+ @SingleRowResult
+ protected static final String FIND_LOCATION = """
+ SELECT
+ x, y, z
+ FROM boards
+ WHERE boards.machine_id = :machine_id
+ AND boards.board_id = :board_id
+ AND boards.may_be_allocated
+ LIMIT 1
+ """;
+
+ /** Get the list of allocation tasks. */
+ @Parameter("job_state")
+ @ResultColumn("req_id")
+ @ResultColumn("job_id")
+ @ResultColumn("num_boards")
+ @ResultColumn("width")
+ @ResultColumn("height")
+ @ResultColumn("board_id")
+ @ResultColumn("machine_id")
+ @ResultColumn("max_dead_boards")
+ @ResultColumn("max_width")
+ @ResultColumn("max_height")
+ @ResultColumn("job_state")
+ @ResultColumn("importance")
+ protected static final String GET_ALLOCATION_TASKS = """
+ SELECT
+ job_request.req_id,
+ job_request.job_id,
+ job_request.num_boards,
+ job_request.width,
+ job_request.height,
+ job_request.board_id,
+ jobs.machine_id AS machine_id,
+ job_request.max_dead_boards,
+ machines.width AS max_width,
+ machines.height AS max_height,
+ jobs.job_state AS job_state,
+ job_request.importance
+ FROM
+ job_request
+ JOIN jobs USING (job_id)
+ JOIN machines USING (machine_id)
+ WHERE job_state = :job_state
+ ORDER BY importance DESC, req_id ASC
+ """;
+
+ /**
+ * Get enabled boards with at least as many reported problems as a given
+ * threshold.
+ */
+ @Parameter("threshold")
+ @ResultColumn("board_id")
+ @ResultColumn("num_reports")
+ @ResultColumn("x")
+ @ResultColumn("y")
+ @ResultColumn("z")
+ @ResultColumn("address")
+ protected static final String GET_REPORTED_BOARDS = """
+ WITH report_counts AS (
+ SELECT
+ board_reports.board_id,
+ COUNT(board_reports.report_id) AS num_reports
+ FROM board_reports
+ JOIN boards USING (board_id)
+ WHERE boards.functioning != 0 -- Ignore disabled boards
+ GROUP BY board_id)
+ SELECT
+ boards.board_id,
+ report_counts.num_reports,
+ boards.x,
+ boards.y,
+ boards.z,
+ boards.address
+ FROM
+ report_counts
+ JOIN boards USING (board_id)
+ WHERE report_counts.num_reports >= :threshold
+ """;
+
+ /** Create a request to change the power status of a board. */
+ @Parameter("job_id")
+ @Parameter("board_id")
+ @Parameter("from_state")
+ @Parameter("to_state")
+ @Parameter("power")
+ @Parameter("fpga_n")
+ @Parameter("fpga_s")
+ @Parameter("fpga_e")
+ @Parameter("fpga_w")
+ @Parameter("fpga_nw")
+ @Parameter("fpga_se")
+ @GeneratesID
+ protected static final String ISSUE_CHANGE_FOR_JOB = """
+ INSERT INTO pending_changes(
+ job_id, board_id, from_state, to_state,
+ power, fpga_n, fpga_e, fpga_se, fpga_s, fpga_w, fpga_nw)
+ VALUES (
+ :job_id, :board_id, :from_state, :to_state,
+ :power, :fpga_n, :fpga_e, :fpga_se, :fpga_s, :fpga_w, :fpga_nw)
+ """;
+
+ /**
+ * Get the links of a machine that have been disabled; each link is
+ * described by the boards it links and the directions the link goes in at
+ * each end.
+ */
+ @Parameter("machine_id")
+ @ResultColumn("board_1_x")
+ @ResultColumn("board_1_y")
+ @ResultColumn("board_1_z")
+ @ResultColumn("board_1_c")
+ @ResultColumn("board_1_f")
+ @ResultColumn("board_1_b")
+ @ResultColumn("board_1_addr")
+ @ResultColumn("dir_1")
+ @ResultColumn("board_2_x")
+ @ResultColumn("board_2_y")
+ @ResultColumn("board_2_z")
+ @ResultColumn("board_2_c")
+ @ResultColumn("board_2_f")
+ @ResultColumn("board_2_b")
+ @ResultColumn("board_2_addr")
+ @ResultColumn("dir_2")
+ protected static final String GET_DEAD_LINKS = """
+ SELECT
+ -- Link end 1: board coords + direction
+ b1.x AS board_1_x, b1.y AS board_1_y, b1.z AS board_1_z,
+ bmp1.cabinet AS board_1_c, bmp1.frame AS board_1_f,
+ b1.board_num AS board_1_b, b1.address AS board_1_addr,
+ dir_1,
+ -- Link end 2: board coords + direction
+ b2.x AS board_2_x, b2.y AS board_2_y, b2.z AS board_2_z,
+ bmp2.cabinet AS board_2_c, bmp2.frame AS board_2_f,
+ b2.board_num AS board_2_b, b2.address AS board_2_addr,
+ dir_2
+ FROM links
+ JOIN boards AS b1 ON board_1 = b1.board_id
+ JOIN boards AS b2 ON board_2 = b2.board_id
+ JOIN bmp AS bmp1 ON bmp1.bmp_id = b1.bmp_id
+ JOIN bmp AS bmp2 ON bmp2.bmp_id = b2.bmp_id
+ WHERE
+ b1.machine_id = :machine_id AND NOT live
+ ORDER BY board_1 ASC, board_2 ASC;
+ """;
+
+ /**
+ * Copy jobs to the historical data DB, and return the IDs of the jobs that
+ * were copied (which will now be safe to delete). Only jobs that are
+ * already completed will ever get copied.
+ *
+ * @see AllocatorTask#tombstone()
+ */
+ @Parameter("grace_period")
+ @ResultColumn("job_id")
+ protected static final String COPY_JOBS_TO_HISTORICAL_DATA = """
+ WITH
+ t(now) AS (VALUES (CAST(strftime('%s','now') AS INTEGER)))
+ INSERT OR IGNORE INTO tombstone.jobs(
+ job_id, machine_id, owner, create_timestamp,
+ width, height, "depth", root_id,
+ keepalive_interval, keepalive_host,
+ death_reason, death_timestamp,
+ original_request,
+ allocation_timestamp, allocation_size,
+ machine_name, owner_name, "group", group_name)
+ SELECT
+ jobs.job_id, jobs.machine_id, jobs.owner, jobs.create_timestamp,
+ jobs.width, jobs.height, jobs."depth", jobs.allocated_root,
+ jobs.keepalive_interval, jobs.keepalive_host,
+ jobs.death_reason, jobs.death_timestamp,
+ original_request,
+ allocation_timestamp, allocation_size,
+ machines.machine_name, user_info.user_name,
+ groups.group_id, groups.group_name
+ FROM
+ jobs
+ JOIN groups USING (group_id)
+ JOIN machines USING (machine_id)
+ JOIN user_info ON jobs.owner = user_info.user_id
+ JOIN t
+ WHERE death_timestamp + :grace_period < t.now
+ RETURNING job_id
+ """;
+
+ /**
+ * Copy board allocation data to the historical data DB, and return the IDs
+ * of the allocation records that were copied (which will now be safe to
+ * delete). Only jobs that are already completed will ever get copied.
+ *
+ * @see AllocatorTask#tombstone()
+ */
+ @Parameter("grace_period")
+ @ResultColumn("alloc_id")
+ protected static final String COPY_ALLOCS_TO_HISTORICAL_DATA = """
+ WITH
+ t(now) AS (VALUES (CAST(strftime('%s','now') AS INTEGER)))
+ INSERT OR IGNORE INTO tombstone.board_allocations(
+ alloc_id, job_id, board_id, allocation_timestamp)
+ SELECT
+ src.alloc_id, src.job_id, src.board_id, src.alloc_timestamp
+ FROM
+ old_board_allocations AS src
+ JOIN jobs USING (job_id)
+ JOIN t
+ WHERE jobs.death_timestamp + :grace_period < t.now
+ RETURNING alloc_id
+ """;
/**
* Insert a request to read a board's temperature data.
@@ -2192,10 +2754,11 @@ public abstract class SQLQueries {
*/
@Parameter("board_id")
@GeneratesID
- protected static final String CREATE_TEMP_READ_REQ =
- "INSERT INTO blacklist_ops(board_id, op, completed) "
- + "VALUES(:board_id, 3, 0)";
-
+ protected static final String CREATE_TEMP_READ_REQ = """
+ INSERT INTO blacklist_ops(
+ board_id, op, completed)
+ VALUES(:board_id, 3, 0)
+ """;
/**
* Read historical allocations to be written to the historical data DB.
@@ -2208,10 +2771,12 @@ public abstract class SQLQueries {
@ResultColumn("job_id")
@ResultColumn("board_id")
@ResultColumn("alloc_timestamp")
- protected static final String READ_HISTORICAL_ALLOCS =
- "SELECT alloc_id, job_id, board_id, alloc_timestamp "
- + "FROM old_board_allocations JOIN jobs USING (job_id) "
- + "WHERE jobs.death_timestamp + :grace_period < UNIX_TIMESTAMP()";
+ protected static final String READ_HISTORICAL_ALLOCS = """
+ SELECT alloc_id, job_id, board_id, alloc_timestamp
+ FROM old_board_allocations
+ JOIN jobs USING (job_id)
+ WHERE jobs.death_timestamp + :grace_period < UNIX_TIMESTAMP()
+ """;
/**
* Read historical jobs to be written to the historical data DB.
@@ -2237,18 +2802,19 @@ public abstract class SQLQueries {
@ResultColumn("user_name")
@ResultColumn("group_id")
@ResultColumn("group_name")
- protected static final String READ_HISTORICAL_JOBS =
- "SELECT job_id, machine_id, owner, create_timestamp, "
- + "jobs.width as width, jobs.height as height, jobs.depth as depth,"
- + "allocated_root, keepalive_interval, keepalive_host, "
- + "death_reason, death_timestamp, original_request, "
- + "allocation_timestamp, allocation_size, "
- + "machine_name, user_name, group_id, group_name "
- + "FROM jobs "
- + "JOIN user_groups USING (group_id) "
- + "JOIN machines USING (machine_id) "
- + "JOIN user_info ON jobs.owner = user_info.user_id "
- + "WHERE death_timestamp + :grace_period < UNIX_TIMESTAMP()";
+ protected static final String READ_HISTORICAL_JOBS = """
+ SELECT job_id, machine_id, owner, create_timestamp,
+ jobs.width AS width, jobs.height AS height, jobs.depth AS depth,
+ allocated_root, keepalive_interval, keepalive_host,
+ death_reason, death_timestamp, original_request,
+ allocation_timestamp, allocation_size,
+ machine_name, user_name, group_id, group_name
+ FROM jobs
+ JOIN user_groups USING (group_id)
+ JOIN machines USING (machine_id)
+ JOIN user_info ON jobs.owner = user_info.user_id
+ WHERE death_timestamp + :grace_period < UNIX_TIMESTAMP()
+ """;
/**
* Write to the historical allocations database.
@@ -2257,10 +2823,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@Parameter("board_id")
@Parameter("allocation_timestamp")
- protected static final String WRITE_HISTORICAL_ALLOCS =
- "INSERT IGNORE INTO board_allocations( "
- + "alloc_id, job_id, board_id, allocation_timestamp) "
- + "VALUES(:alloc_id, :job_id, :board_id, :allocation_timestamp)";
+ protected static final String WRITE_HISTORICAL_ALLOCS = """
+ INSERT IGNORE INTO board_allocations(
+ alloc_id, job_id, board_id, allocation_timestamp)
+ VALUES(:alloc_id, :job_id, :board_id, :allocation_timestamp)
+ """;
/**
* Write to the historical jobs database.
@@ -2284,20 +2851,21 @@ public abstract class SQLQueries {
@Parameter("owner_name")
@Parameter("group_id")
@Parameter("group_name")
- protected static final String WRITE_HISTORICAL_JOBS =
- "INSERT IGNORE INTO jobs( "
- + "job_id, machine_id, owner, create_timestamp, "
- + "width, height, depth, root_id, "
- + "keepalive_interval, keepalive_host, "
- + "death_reason, death_timestamp, "
- + "original_request, allocation_timestamp, allocation_size, "
- + "machine_name, owner_name, group_id, group_name) "
- + "VALUES(:job_id, :machine_id, :owner, :create_timestamp, "
- + ":width, :height, :depth, :root_id, "
- + ":keepalive_interval, :keepalive_host, "
- + ":death_reason, :death_timestamp, "
- + ":original_request, :allocation_timestamp, :allocation_size, "
- + ":machine_name, :owner_name, :group_id, :group_name)";
+ protected static final String WRITE_HISTORICAL_JOBS = """
+ INSERT IGNORE INTO jobs(
+ job_id, machine_id, owner, create_timestamp,
+ width, height, depth, root_id,
+ keepalive_interval, keepalive_host,
+ death_reason, death_timestamp,
+ original_request, allocation_timestamp, allocation_size,
+ machine_name, owner_name, group_id, group_name)
+ VALUES(:job_id, :machine_id, :owner, :create_timestamp,
+ :width, :height, :depth, :root_id,
+ :keepalive_interval, :keepalive_host,
+ :death_reason, :death_timestamp,
+ :original_request, :allocation_timestamp, :allocation_size,
+ :machine_name, :owner_name, :group_id, :group_name)
+ """;
/**
* Set the NMPI session for a Job.
@@ -2305,10 +2873,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@Parameter("session_id")
@Parameter("quota_units")
- protected static final String SET_JOB_SESSION =
- "INSERT IGNORE INTO job_nmpi_session ( "
- + "job_id, session_id, quota_units) "
- + "VALUES(:job_id, :session_id, :quota_units)";
+ protected static final String SET_JOB_SESSION = """
+ INSERT IGNORE INTO job_nmpi_session (
+ job_id, session_id, quota_units)
+ VALUES(:job_id, :session_id, :quota_units)
+ """;
/**
* Set the NMPI Job for a Job.
@@ -2316,10 +2885,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@Parameter("nmpi_job_id")
@Parameter("quota_units")
- protected static final String SET_JOB_NMPI_JOB =
- "INSERT IGNORE INTO job_nmpi_job ( "
- + "job_id, nmpi_job_id, quota_units) "
- + "VALUES(:job_id, :nmpi_job_id, :quota_units)";
+ protected static final String SET_JOB_NMPI_JOB = """
+ INSERT IGNORE INTO job_nmpi_job (
+ job_id, nmpi_job_id, quota_units)
+ VALUES(:job_id, :nmpi_job_id, :quota_units)
+ """;
/**
* Get the NMPI Session for a Job.
@@ -2327,9 +2897,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@ResultColumn("session_id")
@ResultColumn("quota_units")
- protected static final String GET_JOB_SESSION =
- "SELECT session_id, quota_units FROM job_nmpi_session "
- + "WHERE job_id=:job_id";
+ protected static final String GET_JOB_SESSION = """
+ SELECT session_id, quota_units
+ FROM job_nmpi_session
+ WHERE job_id = :job_id
+ """;
/**
* Get the NMPI Job for a Job.
@@ -2337,9 +2909,11 @@ public abstract class SQLQueries {
@Parameter("job_id")
@ResultColumn("nmpi_job_id")
@ResultColumn("quota_units")
- protected static final String GET_JOB_NMPI_JOB =
- "SELECT nmpi_job_id, quota_units FROM job_nmpi_job "
- + "WHERE job_id=:job_id";
+ protected static final String GET_JOB_NMPI_JOB = """
+ SELECT nmpi_job_id, quota_units
+ FROM job_nmpi_job
+ WHERE job_id = :job_id
+ """;
// SQL loaded from files because it is too complicated otherwise!
@@ -2593,8 +3167,10 @@ public abstract class SQLQueries {
protected Resource findBoardByIPAddress;
/**
- * Get jobs on a machine that have changes that can be processed. (A policy
- * of how long after switching a board on or off is applied.)
+ * Get jobs on a machine that have changes that can be processed. This
+ * respects a machine-level policy on how long a board must be switched off
+ * before it can be switched on again, and how long a board must be switched
+ * on before it can be switched off.
*/
@Parameter("machine_id")
@ResultColumn("job_id")
@@ -2603,8 +3179,8 @@ public abstract class SQLQueries {
/**
* Get the set of boards at some coordinates within a triad rectangle that
- * are connected (i.e., have at least one path over enableable links) to the
- * root board.
+ * are connected (i.e., have at least one path over enableable links within
+ * the allocation) to the root board.
*
* @see AllocatorTask
*/
@@ -2618,56 +3194,4 @@ public abstract class SQLQueries {
@ResultColumn("board_id")
@Value("classpath:queries/connected_boards_at_coords.sql")
protected Resource getConnectedBoards;
-
- /** Get the links of a machine that have been disabled. */
- @Parameter("machine_id")
- @ResultColumn("board_1_x")
- @ResultColumn("board_1_y")
- @ResultColumn("board_1_z")
- @ResultColumn("board_1_c")
- @ResultColumn("board_1_f")
- @ResultColumn("board_1_b")
- @ResultColumn("board_1_addr")
- @ResultColumn("dir_1")
- @ResultColumn("board_2_x")
- @ResultColumn("board_2_y")
- @ResultColumn("board_2_z")
- @ResultColumn("board_2_c")
- @ResultColumn("board_2_f")
- @ResultColumn("board_2_b")
- @ResultColumn("board_2_addr")
- @ResultColumn("dir_2")
- @Value("classpath:queries/get_dead_links.sql")
- protected Resource getDeadLinks;
-
- /** Get the list of allocation tasks. */
- @Parameter("job_state")
- @ResultColumn("req_id")
- @ResultColumn("job_id")
- @ResultColumn("num_boards")
- @ResultColumn("width")
- @ResultColumn("height")
- @ResultColumn("board_id")
- @ResultColumn("machine_id")
- @ResultColumn("max_dead_boards")
- @ResultColumn("max_width")
- @ResultColumn("max_height")
- @ResultColumn("job_state")
- @ResultColumn("importance")
- @Value("classpath:queries/get_allocation_tasks.sql")
- protected Resource getAllocationTasks;
-
- /**
- * Get enabled boards with at least as many reported problems as a given
- * threshold.
- */
- @Parameter("threshold")
- @ResultColumn("board_id")
- @ResultColumn("num_reports")
- @ResultColumn("x")
- @ResultColumn("y")
- @ResultColumn("z")
- @ResultColumn("address")
- @Value("classpath:queries/get_reported_boards.sql")
- protected Resource getReportedBoards;
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Utils.java
index d503be040d..0d05e442cb 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Utils.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Utils.java
@@ -92,8 +92,8 @@ private static String trimSQLComments(String sql) {
*/
public static boolean isBusy(DataAccessException exception) {
var root = exception.getMostSpecificCause();
- if (root instanceof SQLException) {
- return isBusy((SQLException) root);
+ if (root instanceof SQLException e) {
+ return isBusy(e);
}
return false;
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardCoords.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardCoords.java
index 83ff08a992..170c648df6 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardCoords.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardCoords.java
@@ -17,8 +17,6 @@
import static java.lang.String.format;
-import java.util.Objects;
-
import com.google.errorprone.annotations.Immutable;
import uk.ac.manchester.spinnaker.alloc.db.Row;
@@ -34,73 +32,30 @@
* Basic coordinates of a board. The result of a DB query.
*
* @author Donal Fellows
+ * @param x
+ * Logical triad X coordinate.
+ * @param y
+ * Logical triad Y coordinate.
+ * @param z
+ * Logical triad Z coordinate.
+ * @param cabinet
+ * Physical cabinet number.
+ * @param frame
+ * Physical frame number.
+ * @param board
+ * Physical board number. May be {@code null} if the board is dead
+ * (e.g., because it is outright absent from the machine).
+ * @param address
+ * IP address of ethernet chip. May be {@code null} if the current
+ * user doesn't have permission to see the board address at this
+ * point, or the board is dead (e.g., because it is outright absent
+ * from the machine).
*/
@Immutable
-public final class BoardCoords {
- /** Logical triad X coordinate. */
- @ValidTriadX
- private final int x;
-
- /** Logical triad Y coordinate. */
- @ValidTriadY
- private final int y;
-
- /** Logical triad Z coordinate. */
- @ValidTriadZ
- private final int z;
-
- /** Physical cabinet number. */
- @ValidCabinetNumber
- private final int cabinet;
-
- /** Physical frame number. */
- @ValidFrameNumber
- private final int frame;
-
- /**
- * Physical board number. May be {@code null} if the board is dead (e.g.,
- * because it is outright absent from the machine).
- */
- @ValidBoardNumber
- private final Integer board;
-
- /**
- * IP address of ethernet chip. May be {@code null} if the current user
- * doesn't have permission to see the board address at this point, or the
- * board is dead (e.g., because it is outright absent from the machine).
- */
- @IPAddress(nullOK = true)
- private final String address;
-
- /**
- * Make an instance from raw results. Uncommon.
- *
- * @param x
- * Logical triad X coordinate
- * @param y
- * Logical triad Y coordinate
- * @param z
- * Logical triad Z coordinate
- * @param cabinet
- * Physical cabinet number
- * @param frame
- * Physical frame number
- * @param board
- * Physical board number, or {@code null}
- * @param address
- * IP address of ethernet chip, or {@code null}
- */
- public BoardCoords(int x, int y, int z, int cabinet, int frame,
- Integer board, String address) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.cabinet = cabinet;
- this.frame = frame;
- this.board = board;
- this.address = address;
- }
-
+public record BoardCoords(@ValidTriadX int x, @ValidTriadY int y,
+ @ValidTriadZ int z, @ValidCabinetNumber int cabinet,
+ @ValidFrameNumber int frame, @ValidBoardNumber Integer board,
+ @IPAddress(nullOK = true) String address) {
/**
* Construct a set of board coordinates from a database row that describes
* them. The common constructor.
@@ -111,84 +66,10 @@ public BoardCoords(int x, int y, int z, int cabinet, int frame,
* Whether the {@link #address} should be shrouded.
*/
public BoardCoords(Row row, boolean shroudAddress) {
- x = row.getInt("x");
- y = row.getInt("y");
- z = row.getInt("z");
- cabinet = row.getInt("cabinet");
- frame = row.getInt("frame");
- board = row.getInteger("board_num");
- address = shroudAddress ? null : row.getString("address");
- }
-
- /**
- * @return Logical triad X coordinate.
- */
- public int getX() {
- return x;
- }
-
- /**
- * @return Logical triad Y coordinate.
- */
- public int getY() {
- return y;
- }
-
- /**
- * @return Logical triad Z coordinate.
- */
- public int getZ() {
- return z;
- }
-
- /**
- * @return Physical cabinet number.
- */
- public int getCabinet() {
- return cabinet;
- }
-
- /**
- * @return Physical frame number.
- */
- public int getFrame() {
- return frame;
- }
-
- /**
- * @return Physical board number. May be {@code null} if the board is dead
- * (e.g., because it is outright absent from the machine).
- */
- public Integer getBoard() {
- return board;
- }
-
- /**
- * @return IP address of ethernet chip. May be {@code null} if the current
- * user doesn't have permission to see the board address at this
- * point, or the board is dead (e.g., because it is outright absent
- * from the machine).
- */
- public String getAddress() {
- return address;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof BoardCoords) {
- var other = (BoardCoords) o;
- return (x == other.x) && (y == other.y) && (z == other.z)
- && (cabinet == other.cabinet) && (frame == other.frame)
- && Objects.equals(board, other.board)
- && Objects.equals(address, other.address);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- // Just uses the triad coordinates
- return x << 16 | y << 8 | z;
+ this(row.getInt("x"), row.getInt("y"), row.getInt("z"),
+ row.getInt("cabinet"), row.getInt("frame"),
+ row.getInteger("board_num"),
+ shroudAddress ? null : row.getString("address"));
}
@Override
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardIssueReport.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardIssueReport.java
index b9b2ba0c66..1af8f8af92 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardIssueReport.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardIssueReport.java
@@ -15,11 +15,10 @@
*/
package uk.ac.manchester.spinnaker.alloc.model;
-import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
-
import java.time.Instant;
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
import uk.ac.manchester.spinnaker.alloc.db.Row;
import uk.ac.manchester.spinnaker.alloc.db.SQLQueries;
@@ -29,21 +28,24 @@
* A report of an issue with a board.
*
* @author Donal Fellows
+ * @param id
+ * The report ID.
+ * @param boardId
+ * The board ID.
+ * @param issue
+ * What did they report?
+ * @param reporter
+ * Who reported it?
+ * @param timestamp
+ * When was it reported?
*/
-@JsonAutoDetect(setterVisibility = NON_PRIVATE)
-public class BoardIssueReport {
- private int id;
-
- private int boardId;
-
- private String issue;
-
- private String reporter;
-
- private Instant timestamp;
-
- /** Create a record. */
- public BoardIssueReport() {
+public record BoardIssueReport(int id, int boardId, String issue,
+ String reporter, Instant timestamp) {
+ @JsonCreator
+ BoardIssueReport(@JsonProperty int id, @JsonProperty int boardId,
+ @JsonProperty String issue, @JsonProperty String reporter,
+ @JsonProperty String timestamp) {
+ this(id, boardId, issue, reporter, Instant.parse(timestamp));
}
/**
@@ -55,55 +57,8 @@ public BoardIssueReport() {
*/
@UsedInJavadocOnly(SQLQueries.class)
public BoardIssueReport(Row row) {
- id = row.getInt("report_id");
- boardId = row.getInt("board_id");
- issue = row.getString("reported_issue");
- reporter = row.getString("reporter_name");
- timestamp = row.getInstant("report_timestamp");
- }
-
- /** @return The report ID. */
- public int getId() {
- return id;
- }
-
- void setId(int id) {
- this.id = id;
- }
-
- /** @return The board ID. */
- public int getBoardId() {
- return boardId;
- }
-
- void setBoardId(int id) {
- this.boardId = id;
- }
-
- /** @return What did they report? */
- public String getIssue() {
- return issue;
- }
-
- void setIssue(String issue) {
- this.issue = issue;
- }
-
- /** @return Who reported it? */
- public String getReporter() {
- return reporter;
- }
-
- void setReporter(String reporter) {
- this.reporter = reporter;
- }
-
- /** @return When was it reported? */
- public Instant getTimestamp() {
- return timestamp;
- }
-
- void setTimestamp(Instant timestamp) {
- this.timestamp = timestamp;
+ this(row.getInt("report_id"), row.getInt("board_id"),
+ row.getString("reported_issue"), row.getString("reporter_name"),
+ row.getInstant("report_timestamp"));
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardRecord.java
index 07e38d15f5..334efb8c1e 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardRecord.java
@@ -21,11 +21,10 @@
import java.util.ArrayList;
import java.util.List;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotBlank;
-
import com.google.errorprone.annotations.Keep;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotBlank;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidCabinetNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidFrameNumber;
@@ -39,8 +38,8 @@
*
* @author Donal Fellows
*/
+@JavaBean
public class BoardRecord {
- // TODO convert to structured form
private Integer id;
private Integer bmpId;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardTemperatures.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardTemperatures.java
index 66be6f6bcc..92d752a2b3 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardTemperatures.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/BoardTemperatures.java
@@ -20,6 +20,7 @@
/**
* A board temperature.
*/
+// Used by JSP, so not a record
public class BoardTemperatures {
/** The board temperature. */
public final double boardTemperature;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/ConnectionInfo.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/ConnectionInfo.java
index afe030780a..4d2b08c572 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/ConnectionInfo.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/ConnectionInfo.java
@@ -18,17 +18,13 @@
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY;
-import java.util.Objects;
-
-import javax.validation.Valid;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.google.errorprone.annotations.Immutable;
+import jakarta.validation.Valid;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
-import uk.ac.manchester.spinnaker.machine.HasChipLocation;
import uk.ac.manchester.spinnaker.spalloc.messages.Connection;
import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly;
import uk.ac.manchester.spinnaker.utils.validation.IPAddress;
@@ -37,10 +33,12 @@
* Describes a connection by its chip and hostname.
*
* @see Connection
+ * @param chip
+ * The chip for the connection.
+ * @param hostname
+ * Where to connect to to talk to the chip.
*/
-@JsonPropertyOrder({
- "chip", "hostname"
-})
+@JsonPropertyOrder({ "chip", "hostname" })
@JsonFormat(shape = ARRAY)
@JsonAutoDetect(setterVisibility = NON_PRIVATE)
/*
@@ -49,51 +47,8 @@
*/
@Immutable
@UsedInJavadocOnly(Connection.class)
-public final class ConnectionInfo {
- @Valid
- private final ChipLocation chip;
-
- @IPAddress
- private final String hostname;
-
- /**
- * Create.
- *
- * @param chip
- * the chip
- * @param hostname
- * the host
- */
- public ConnectionInfo(HasChipLocation chip, String hostname) {
- this.chip = chip.asChipLocation();
- this.hostname = hostname;
- }
-
- /** @return The chip for the connection. */
- public ChipLocation getChip() {
- return chip;
- }
-
- /** @return Where to connect to to talk to the chip. */
- public String getHostname() {
- return hostname;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ConnectionInfo) {
- var c = (ConnectionInfo) other;
- return Objects.equals(chip, c.chip)
- && Objects.equals(hostname, c.hostname);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(hostname, chip);
- }
-
+public record ConnectionInfo(@Valid ChipLocation chip,
+ @IPAddress String hostname) {
@Override
public String toString() {
return "Connection(" + chip + "@" + hostname + ")";
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/DownLink.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/DownLink.java
index 68ee50abdb..336ae425e2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/DownLink.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/DownLink.java
@@ -17,43 +17,35 @@
import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.errorprone.annotations.Immutable;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+
/**
* Describes a link that is disabled.
*
* @author Donal Fellows
+ * @param end1
+ * One end of the down link.
+ * @param end2
+ * The other end of the down link.
*/
@Immutable
@JsonFormat(shape = ARRAY)
-public final class DownLink {
+public record DownLink(@Valid DownLink.End end1, @Valid DownLink.End end2) {
/**
* Describes one end of a link that is disabled.
*
* @author Donal Fellows
+ * @param board
+ * On what board is this end of the link.
+ * @param direction
+ * In which direction does this end of the link go?
*/
@Immutable
- public static final class End {
- private End(BoardCoords board, Direction direction) {
- this.board = board;
- this.direction = direction;
- }
-
- /**
- * On what board is this end of the link.
- */
- @Valid
- public final BoardCoords board;
-
- /**
- * In which direction does this end of the link go?
- */
- @NotNull
- public final Direction direction;
+ public record End(@Valid BoardCoords board, @NotNull Direction direction) {
}
/**
@@ -70,15 +62,6 @@ private End(BoardCoords board, Direction direction) {
*/
public DownLink(BoardCoords board1, Direction dir1, BoardCoords board2,
Direction dir2) {
- end1 = new End(board1, dir1);
- end2 = new End(board2, dir2);
+ this(new End(board1, dir1), new End(board2, dir2));
}
-
- /** One end of the down link. */
- @Valid
- public final DownLink.End end1;
-
- /** The other end of the down link. */
- @Valid
- public final DownLink.End end2;
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/GroupRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/GroupRecord.java
index 889b618954..a6590c6fb8 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/GroupRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/GroupRecord.java
@@ -23,18 +23,18 @@
import java.util.Map;
import java.util.Optional;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Null;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Null;
import uk.ac.manchester.spinnaker.alloc.db.Row;
/**
* The description and model of a group. POJO class; changes not automatically
* reflected in the DB.
*/
+@JavaBean
@JsonAutoDetect(setterVisibility = NON_PRIVATE)
public final class GroupRecord {
/** The type of a group. */
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JavaBean.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JavaBean.java
new file mode 100644
index 0000000000..473d228591
--- /dev/null
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JavaBean.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 The University of Manchester
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package uk.ac.manchester.spinnaker.alloc.model;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks that a particular class is used as a Java Bean because it is used as
+ * part of a the MVC model. Java Beans can't be records currently, as JSTL does
+ * not support them.
+ *
+ * @author Donal Fellows
+ */
+@Retention(SOURCE)
+@Target(TYPE)
+@interface JavaBean {
+ /**
+ * Whether this is a modifiable Java Bean.
+ *
+ * @return Whether this class has any setters.
+ */
+ boolean modifiable() default true;
+}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobDescription.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobDescription.java
index b6f17263cd..5478dc5eba 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobDescription.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobDescription.java
@@ -24,9 +24,8 @@
import java.util.List;
import java.util.Optional;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
import uk.ac.manchester.spinnaker.machine.ValidMachineHeight;
import uk.ac.manchester.spinnaker.machine.ValidMachineWidth;
@@ -54,6 +53,7 @@
*
* (That's actually slightly edited output from {@code spalloc-job -info})
*/
+@JavaBean
public class JobDescription {
private int id;
@@ -285,7 +285,7 @@ public void setRequestBytes(byte[] bytes) {
* @return The width of the allocation in triads. 0 if not yet allocated.
*/
public int getTriadWidth() {
- var stats = boards.stream().collect(summarizingInt(BoardCoords::getX));
+ var stats = boards.stream().collect(summarizingInt(BoardCoords::x));
if (stats.getCount() < 1) {
return 0;
}
@@ -296,7 +296,7 @@ public int getTriadWidth() {
* @return The height of the allocation in triads. 0 if not yet allocated.
*/
public int getTriadHeight() {
- var stats = boards.stream().collect(summarizingInt(BoardCoords::getY));
+ var stats = boards.stream().collect(summarizingInt(BoardCoords::y));
if (stats.getCount() < 1) {
return 0;
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobListEntryRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobListEntryRecord.java
index 0a5ec4ada5..9c24c93c29 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobListEntryRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobListEntryRecord.java
@@ -23,9 +23,9 @@
import java.util.List;
import java.util.Optional;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.PositiveOrZero;
/**
* Entry in a table of machines. The table is like this:
@@ -72,6 +72,7 @@
* ...
*
*/
+@JavaBean
public class JobListEntryRecord {
private int id;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineDescription.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineDescription.java
index e9be060655..b7650fabfe 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineDescription.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineDescription.java
@@ -21,10 +21,9 @@
import java.util.List;
import java.util.Optional;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.PositiveOrZero;
-
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.PositiveOrZero;
import uk.ac.manchester.spinnaker.machine.board.ValidTriadHeight;
import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth;
import uk.ac.manchester.spinnaker.utils.MappableIterable;
@@ -32,6 +31,7 @@
/**
* Descriptive detail for a machine. Used for HTML generation.
*/
+@JavaBean
public class MachineDescription {
private int id;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineListEntryRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineListEntryRecord.java
index c91e697642..b07afb05f3 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineListEntryRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineListEntryRecord.java
@@ -21,9 +21,9 @@
import java.util.List;
import java.util.Optional;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.PositiveOrZero;
/**
* Entry in a table of machines. The table is like this:
@@ -58,6 +58,7 @@
* | ...
*
*/
+@JavaBean
public class MachineListEntryRecord {
private int id;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineTagging.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineTagging.java
index 156e3243dc..78f269e864 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineTagging.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MachineTagging.java
@@ -23,10 +23,9 @@
import java.util.List;
import java.util.Set;
-import javax.validation.constraints.NotBlank;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import jakarta.validation.constraints.NotBlank;
import uk.ac.manchester.spinnaker.alloc.db.Row;
import uk.ac.manchester.spinnaker.alloc.db.SQLQueries;
import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly;
@@ -36,6 +35,7 @@
*
* @author Donal Fellows
*/
+@JavaBean
@JsonAutoDetect(setterVisibility = NON_PRIVATE)
public class MachineTagging {
@NotBlank
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MemberRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MemberRecord.java
index 67d7f75a89..0048e4362d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MemberRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/MemberRecord.java
@@ -19,10 +19,10 @@
import java.net.URI;
-import javax.validation.constraints.NotBlank;
-
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.validation.constraints.NotBlank;
+
/**
* Description of the membership of one user in one group.
*
@@ -30,6 +30,7 @@
* @see GroupRecord
* @author Donal Fellows
*/
+@JavaBean
@JsonInclude(NON_NULL)
public class MemberRecord {
private int id;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/PasswordChangeRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/PasswordChangeRecord.java
index a486ddf680..cf5ed4fea0 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/PasswordChangeRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/PasswordChangeRecord.java
@@ -17,9 +17,9 @@
import static java.util.Objects.requireNonNull;
-import javax.validation.constraints.AssertFalse;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.AssertFalse;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotBlank;
/**
* Describes basic information about a user that they'd use to change their
@@ -27,6 +27,7 @@
*
* @author Donal Fellows
*/
+@JavaBean
public class PasswordChangeRecord {
private int userId;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/TagList.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/TagList.java
index 05aba41a43..439c0f012e 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/TagList.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/TagList.java
@@ -25,8 +25,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
-import javax.validation.Payload;
-import javax.validation.constraints.Pattern;
+import jakarta.validation.Payload;
+import jakarta.validation.constraints.Pattern;
/**
* Validates that a string looks like a comma-separated tag list.
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/UserRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/UserRecord.java
index 59021a72bd..bdf26d49c2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/UserRecord.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/UserRecord.java
@@ -25,16 +25,15 @@
import java.time.Instant;
import java.util.Map;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Null;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Null;
import uk.ac.manchester.spinnaker.alloc.db.Row;
import uk.ac.manchester.spinnaker.alloc.db.SQLQueries;
import uk.ac.manchester.spinnaker.alloc.security.TrustLevel;
@@ -46,6 +45,7 @@
* this class but the service itself will not respect being asked to change
* them.
*/
+@JavaBean
@JsonAutoDetect(setterVisibility = NON_PRIVATE)
public final class UserRecord {
private Integer userId;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Job.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Job.java
index 373572e280..9ed49d5bd2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Job.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Job.java
@@ -52,7 +52,7 @@ public Integer getId() {
* @param id
* the id to set
*/
- public void setId(final Integer id) {
+ public void setId(Integer id) {
this.id = id;
}
@@ -71,7 +71,7 @@ public String getCollab() {
* @param collab
* the collab to set
*/
- public void setCollab(final String collab) {
+ public void setCollab(String collab) {
this.collab = collab;
}
@@ -90,7 +90,7 @@ public String getStatus() {
* @param status
* the status to set
*/
- public void setStatus(final String status) {
+ public void setStatus(String status) {
this.status = status;
}
@@ -109,7 +109,7 @@ public String getUserId() {
* @param userId
* the userId to set
*/
- public void setUserId(final String userId) {
+ public void setUserId(String userId) {
this.userId = userId;
}
@@ -128,7 +128,7 @@ public ResourceUsage getResourceUsage() {
* @param resourceUsage
* the resourceUsage to set
*/
- public void setResourceUsage(final ResourceUsage resourceUsage) {
+ public void setResourceUsage(ResourceUsage resourceUsage) {
this.resourceUsage = resourceUsage;
}
@@ -143,7 +143,7 @@ public void setResourceUsage(final ResourceUsage resourceUsage) {
* @hidden
*/
@JsonAnySetter
- public void set(final String name, final Object value) {
+ void set(String name, Object value) {
// Ignore any other values
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/JobResourceUpdate.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/JobResourceUpdate.java
index 188a17d718..c3b632c081 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/JobResourceUpdate.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/JobResourceUpdate.java
@@ -30,19 +30,19 @@ public class JobResourceUpdate {
/**
* Get the count of how much resource has been used by the job.
*
- * @return the resourceUsage
+ * @return the resource usage
*/
public ResourceUsage getResourceUsage() {
return resourceUsage;
}
/**
- * Sets the resourceUsage.
+ * Sets the resource usage.
*
* @param resourceUsage
- * the resourceUsage to set
+ * the resource usage to set
*/
- public void setResourceUsage(final ResourceUsage resourceUsage) {
+ public void setResourceUsage(ResourceUsage resourceUsage) {
this.resourceUsage = resourceUsage;
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/NMPIv3API.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/NMPIv3API.java
index b2621443d5..2cbcafe194 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/NMPIv3API.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/NMPIv3API.java
@@ -19,20 +19,20 @@
import java.util.List;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
/**
* The REST API for the NMPI Service.
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Project.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Project.java
index 6215d8e621..124c76d3fb 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Project.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Project.java
@@ -53,7 +53,7 @@ public void setQuotas(List quotas) {
* @hidden
*/
@JsonAnySetter
- public void set(final String name, final Object value) {
+ void set(String name, Object value) {
// Ignore any other values
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Quota.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Quota.java
index c43be1d01c..2d5a3e0a1d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Quota.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/Quota.java
@@ -105,7 +105,7 @@ public void setUnits(String units) {
* @hidden
*/
@JsonAnySetter
- public void set(final String name, final Object value) {
+ void set(String name, Object value) {
// Ignore any other values
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionRequest.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionRequest.java
index e0018d9b7c..8149e1db88 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionRequest.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionRequest.java
@@ -55,7 +55,7 @@ public String getCollab() {
* @param collab
* the collab to set
*/
- public void setCollab(final String collab) {
+ public void setCollab(String collab) {
this.collab = collab;
}
@@ -74,7 +74,7 @@ public String getUserId() {
* @param userId
* the userId to set
*/
- public void setUserId(final String userId) {
+ public void setUserId(String userId) {
this.userId = userId;
}
@@ -119,7 +119,7 @@ public void setHardwareConfig(Map hardwareConfig) {
* @hidden
*/
@JsonAnySetter
- public void set(final String name, final Object value) {
+ void set(String name, Object value) {
// Ignore any other values
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResourceUpdate.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResourceUpdate.java
index 64a127e85c..c3eda573e9 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResourceUpdate.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResourceUpdate.java
@@ -45,26 +45,26 @@ public String getStatus() {
* @param status
* the status to set
*/
- public void setStatus(final String status) {
+ public void setStatus(String status) {
this.status = status;
}
/**
* Get the count of how much resource has been used by the job.
*
- * @return the resourceUsage
+ * @return the resource usage
*/
public ResourceUsage getResourceUsage() {
return resourceUsage;
}
/**
- * Sets the resourceUsage.
+ * Sets the resource usage.
*
* @param resourceUsage
- * the resourceUsage to set
+ * the resource usage to set
*/
- public void setResourceUsage(final ResourceUsage resourceUsage) {
+ public void setResourceUsage(ResourceUsage resourceUsage) {
this.resourceUsage = resourceUsage;
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResponse.java
index 4ec5587094..76bf86dc2d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/SessionResponse.java
@@ -35,12 +35,12 @@ public Integer getId() {
}
/**
- * Sets the id.
+ * Sets the ID.
*
* @param id
* the id to set
*/
- public void setId(final Integer id) {
+ public void setId(Integer id) {
this.id = id;
}
@@ -55,7 +55,7 @@ public void setId(final Integer id) {
* @hidden
*/
@JsonAnySetter
- public void set(final String name, final Object value) {
+ void set(String name, Object value) {
// Ignore any other values
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/package-info.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/package-info.java
index ef65e44c05..a0d5068fd6 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/package-info.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/nmpi/package-info.java
@@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
- * Interaction with the NMPI interface.
+ * Model classes for interaction with the NMPI interface.
*/
package uk.ac.manchester.spinnaker.alloc.nmpi;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyCore.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyCore.java
index 0c746c79d0..dbc7da6dbd 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyCore.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyCore.java
@@ -16,8 +16,6 @@
package uk.ac.manchester.spinnaker.alloc.proxy;
import static java.net.InetAddress.getByName;
-import static java.nio.ByteBuffer.allocate;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.web.socket.CloseStatus.BAD_DATA;
@@ -25,6 +23,7 @@
import static uk.ac.manchester.spinnaker.alloc.proxy.ProxyOp.CLOSE;
import static uk.ac.manchester.spinnaker.alloc.proxy.ProxyOp.OPEN_UNCONNECTED;
import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import static uk.ac.manchester.spinnaker.utils.UnitConstants.KILOBYTE;
import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC;
@@ -49,7 +48,6 @@
import uk.ac.manchester.spinnaker.alloc.model.ConnectionInfo;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
-import uk.ac.manchester.spinnaker.utils.ValueHolder;
/**
* The main proxy class for a particular web socket session. It's bound to a
@@ -125,10 +123,10 @@ public class ProxyCore implements AutoCloseable {
this.localHost = localHost;
for (var ci : connections) {
try {
- hosts.put(ci.getChip(), getByName(ci.getHostname()));
+ hosts.put(ci.chip(), getByName(ci.hostname()));
} catch (UnknownHostException e) {
log.warn("unexpectedly unknown board address: {}",
- ci.getHostname(), e);
+ ci.hostname(), e);
}
}
recvFrom = Set.copyOf(hosts.values());
@@ -140,21 +138,20 @@ private interface Impl {
}
private Impl decode(int opcode) {
- switch (ProxyOp.values()[opcode]) {
- case OPEN:
- return this::openConnectedChannel;
- case CLOSE:
- return this::closeChannel;
- case MESSAGE:
- return this::sendMessage;
- case OPEN_UNCONNECTED:
- return this::openUnconnectedChannel;
- case MESSAGE_TO:
- return this::sendMessageTo;
- default:
- log.warn("unexpected proxy opcode: {}", opcode);
- throw new IllegalArgumentException("bad opcode");
- }
+ return switch (ProxyOp.values()[opcode]) {
+ case OPEN -> this::openConnectedChannel;
+ case CLOSE -> this::closeChannel;
+ case MESSAGE -> this::sendMessage;
+ case OPEN_UNCONNECTED -> this::openUnconnectedChannel;
+ case MESSAGE_TO -> this::sendMessageTo;
+ default -> this::unexpectedMessage;
+ };
+ }
+
+ private ByteBuffer unexpectedMessage(ByteBuffer message) {
+ int opcode = message.getInt(0);
+ log.error("unexpected message: {}", opcode);
+ return composeError(-1, new Exception("unexpected message: " + opcode));
}
/**
@@ -186,7 +183,7 @@ public final void handleClientMessage(ByteBuffer message)
private static ByteBuffer response(ProxyOp op, int correlationId,
int additionalWords) {
int nWords = RESPONSE_WORDS + additionalWords;
- var msg = allocate(nWords * WORD_SIZE).order(LITTLE_ENDIAN);
+ var msg = alloc(nWords * WORD_SIZE);
msg.putInt(op.ordinal());
msg.putInt(correlationId);
return msg;
@@ -212,8 +209,7 @@ private static ByteBuffer composeError(int corId, Exception ex) {
msg = null;
continue;
}
- var data = allocate(WORD_SIZE + WORD_SIZE + msgBytes.length);
- data.order(LITTLE_ENDIAN);
+ var data = alloc(WORD_SIZE + WORD_SIZE + msgBytes.length);
data.putInt(ProxyOp.ERROR.ordinal());
data.putInt(corId);
data.put(msgBytes);
@@ -318,17 +314,15 @@ protected ByteBuffer openUnconnectedChannel(ByteBuffer message) {
assertEndOfMessage(message);
try {
- var localAddress = new ValueHolder();
- var localPort = new ValueHolder();
- int id = openUnconnected(localAddress, localPort);
- var addr = localAddress.getValue().getAddress();
+ var uc = openUnconnected();
+ var addr = uc.localAddr().getAddress();
log.debug("Unconnected channel local address: {}", addr);
var msg = response(OPEN_UNCONNECTED, corId,
ID_WORDS + IP_ADDR_AND_PORT_WORDS);
- msg.putInt(id);
+ msg.putInt(uc.id());
msg.put(addr);
- msg.putInt(localPort.getValue());
+ msg.putInt(uc.localPort());
return msg;
} catch (Exception e) {
log.error("failed to open unconnected channel", e);
@@ -336,8 +330,10 @@ protected ByteBuffer openUnconnectedChannel(ByteBuffer message) {
}
}
- private int openUnconnected(ValueHolder localAddress,
- ValueHolder localPort) throws IOException {
+ private record Unconnected(int id, InetAddress localAddr, int localPort) {
+ }
+
+ private Unconnected openUnconnected() throws IOException {
int id = idIssuer.getAsInt();
var conn = new ProxyUDPConnection(session, null, 0, id,
() -> removeConnection(id), localHost);
@@ -350,10 +346,7 @@ private int openUnconnected(ValueHolder localAddress,
log.info("opened proxy unconnected channel {}:{} from {}:{}", session,
id, who, port);
- // Arrange for values to be sent out
- localAddress.setValue(who);
- localPort.setValue(port);
- return id;
+ return new Unconnected(id, who, port);
}
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyUDPConnection.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyUDPConnection.java
index 414fb7c1dc..6d1b8dd5fd 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyUDPConnection.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyUDPConnection.java
@@ -16,10 +16,9 @@
package uk.ac.manchester.spinnaker.alloc.proxy;
import static java.lang.Thread.currentThread;
-import static java.nio.ByteBuffer.allocate;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.connections.UDPConnection.TrafficClass.IPTOS_THROUGHPUT;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import java.io.IOException;
import java.net.InetAddress;
@@ -70,7 +69,7 @@ public class ProxyUDPConnection extends UDPConnection> {
super(localHost, null, remoteHost, remotePort, IPTOS_THROUGHPUT);
this.session = session;
this.emergencyRemove = emergencyRemove;
- workingBuffer = allocate(WORKING_BUFFER_SIZE).order(LITTLE_ENDIAN);
+ workingBuffer = alloc(WORKING_BUFFER_SIZE);
// Fixed header for this particular connection
workingBuffer.putInt(ProxyOp.MESSAGE.ordinal());
workingBuffer.putInt(id);
@@ -259,11 +258,11 @@ private void mainLoop(Set recvFrom) throws IOException {
continue;
}
// SECURITY: drop any packet not from an allocated board
- if (!recvFrom.contains(packet.getAddress().getAddress())) {
- log.debug("dropped packet from {}", packet.getAddress());
+ if (!recvFrom.contains(packet.address().getAddress())) {
+ log.debug("dropped packet from {}", packet.address());
continue;
}
- handleReceivedMessage(packet.getByteBuffer());
+ handleReceivedMessage(packet.byteBuffer());
}
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/SpinWSHandler.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/SpinWSHandler.java
index 277ba98558..b32fbe8bc9 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/SpinWSHandler.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/SpinWSHandler.java
@@ -15,10 +15,10 @@
*/
package uk.ac.manchester.spinnaker.alloc.proxy;
+import static jakarta.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
import static java.lang.Integer.parseInt;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.util.concurrent.Executors.newCachedThreadPool;
-import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.alloc.proxy.Utils.getFieldFromTemplate;
@@ -31,9 +31,6 @@
import java.util.Optional;
import java.util.concurrent.ExecutorService;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.ServerHttpRequest;
@@ -48,6 +45,8 @@
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.util.UriTemplate;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Job;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AccessDeniedExceptionMapper.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AccessDeniedExceptionMapper.java
index 2a4e5b5022..58be167e73 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AccessDeniedExceptionMapper.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AccessDeniedExceptionMapper.java
@@ -15,19 +15,12 @@
*/
package uk.ac.manchester.spinnaker.alloc.security;
+import static jakarta.ws.rs.core.Response.status;
+import static jakarta.ws.rs.core.Response.Status.FORBIDDEN;
import static java.util.stream.Collectors.toSet;
-import static javax.ws.rs.core.Response.status;
-import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
import org.slf4j.Logger;
import org.springframework.context.annotation.Role;
import org.springframework.security.access.AccessDeniedException;
@@ -37,6 +30,12 @@
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.stereotype.Component;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly;
/**
@@ -64,15 +63,13 @@ class AccessDeniedExceptionMapper
public Response toResponse(AccessDeniedException exception) {
// Actually produce useful logging; the default is ghastly!
var p = req.getUserPrincipal();
- if (p instanceof AbstractAuthenticationToken) {
- var who = (AbstractAuthenticationToken) p;
+ if (p instanceof AbstractAuthenticationToken who) {
log.warn("access denied: {} : {} {}", ui.getAbsolutePath(),
who.getName(),
who.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(toSet()));
- } else if (p instanceof OAuth2AuthenticatedPrincipal) {
- var who = (OAuth2AuthenticatedPrincipal) p;
+ } else if (p instanceof OAuth2AuthenticatedPrincipal who) {
log.warn("access denied: {} : {} {}", ui.getAbsolutePath(),
who.getName(),
who.getAuthorities().stream()
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AnyTypeMethodSecurityExpressionHandler.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AnyTypeMethodSecurityExpressionHandler.java
index cd7285755b..128b629c2d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AnyTypeMethodSecurityExpressionHandler.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AnyTypeMethodSecurityExpressionHandler.java
@@ -54,8 +54,8 @@ public Object filter(Object target, Expression expr,
|| target instanceof Map || target instanceof Stream) {
return super.filter(target, expr, ctx);
}
- if (target instanceof Optional) {
- return filterOptional((Optional>) target, expr, ctx);
+ if (target instanceof Optional> opt) {
+ return filterOptional(opt, expr, ctx);
} else {
return filterOptional(Optional.of(target), expr, ctx).orElse(null);
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AppAuthTransformationFilter.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AppAuthTransformationFilter.java
index 5f83a5e8f6..61eedaa982 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AppAuthTransformationFilter.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/AppAuthTransformationFilter.java
@@ -22,11 +22,11 @@
import java.io.IOException;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -94,8 +94,7 @@ protected void doFilterInternal(HttpServletRequest request,
private static Authentication getSavedToken(HttpSession session) {
if (nonNull(session)) {
var o = session.getAttribute(TOKEN);
- if (o instanceof Token) {
- var t = (Token) o;
+ if (o instanceof Token t) {
if (t.isValid(session)) {
return t.getAuth();
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/BasicAuthEntryPoint.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/BasicAuthEntryPoint.java
index 3771ea60cd..0895712f7a 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/BasicAuthEntryPoint.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/BasicAuthEntryPoint.java
@@ -15,22 +15,21 @@
*/
package uk.ac.manchester.spinnaker.alloc.security;
+import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static java.lang.String.format;
import static java.util.stream.Collectors.joining;
-import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.IOException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AuthProperties;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthProviderImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthProviderImpl.java
index d2dc27506f..c909935225 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthProviderImpl.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthProviderImpl.java
@@ -32,6 +32,7 @@
import static uk.ac.manchester.spinnaker.alloc.security.TrustLevel.USER;
import static uk.ac.manchester.spinnaker.utils.OptionalUtils.ifElse;
+import java.io.Serial;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -40,8 +41,8 @@
import java.util.Optional;
import java.util.regex.Pattern;
-import javax.annotation.PostConstruct;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,7 +50,6 @@
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.security.access.intercept.RunAsUserToken;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
@@ -97,6 +97,7 @@
* @see AuthProperties Configuration properties
* @author Donal Fellows
*/
+@SuppressWarnings("deprecation")
@Service
public class LocalAuthProviderImpl extends DatabaseAwareBean
implements LocalAuthenticationProvider {
@@ -189,6 +190,7 @@ private void initUserIfNecessary() {
}
private static final class SetupException extends RuntimeException {
+ @Serial
private static final long serialVersionUID = -3915472090182223715L;
SetupException(String message) {
@@ -230,28 +232,26 @@ public Authentication authenticate(Authentication auth)
}
try {
- if (auth instanceof UsernamePasswordAuthenticationToken) {
- return authenticateDirect(
- (UsernamePasswordAuthenticationToken) auth);
- } else if (auth instanceof OAuth2AuthenticationToken) {
+ if (auth instanceof UsernamePasswordAuthenticationToken userpass) {
+ return authenticateDirect(userpass);
+ } else if (auth instanceof OAuth2AuthenticationToken oauth) {
/*
* Technically, at this point we're already authenticated as
* we've checked that the token from Keycloak is valid. We still
* have to take an authorization decision though.
*/
- var user = ((OAuth2AuthenticationToken) auth).getPrincipal();
+ var user = oauth.getPrincipal();
return authorizeOpenId(
authProps.getOpenid().getUsernamePrefix()
+ user.getAttribute(PREFERRED_USERNAME),
user.getAttribute(SUB), new OriginatingCredential(user),
auth.getAuthorities());
- } else if (auth instanceof BearerTokenAuthentication) {
+ } else if (auth instanceof BearerTokenAuthentication bearerAuth) {
/*
* Technically, at this point we're already authenticated as
* we've checked that the token from Keycloak is valid. We still
* have to take an authorization decision though.
*/
- var bearerAuth = (BearerTokenAuthentication) auth;
var token = bearerAuth.getToken();
return authorizeOpenId(
authProps.getOpenid().getUsernamePrefix()
@@ -300,7 +300,7 @@ public Authentication updateAuthentication(HttpServletRequest req,
/** The classes that we know we don't ever want to handle. */
private static final Class>[] UNSUPPORTED_AUTH_TOKEN_CLASSES = {
AnonymousAuthenticationToken.class, RememberMeAuthenticationToken.class,
- RunAsUserToken.class, TestingAuthenticationToken.class
+ TestingAuthenticationToken.class
};
@Override
@@ -337,6 +337,7 @@ static boolean isUnsupportedAuthTokenClass(Class> cls) {
private static final class PerformedUsernamePasswordAuthenticationToken
extends UsernamePasswordAuthenticationToken
implements AlreadyDoneMarker {
+ @Serial
private static final long serialVersionUID = -3164620207079316329L;
PerformedUsernamePasswordAuthenticationToken(String name,
@@ -424,19 +425,14 @@ private Authentication authorizeOpenId(String name, String subject,
}
/** Holds either a {@link OAuth2User} or a {@link Jwt}. */
- private static final class OriginatingCredential {
- private final OAuth2User user;
-
- private final OAuth2AccessToken token;
-
+ private record OriginatingCredential(OAuth2User user,
+ OAuth2AccessToken token) {
OriginatingCredential(OAuth2User user) {
- this.user = requireNonNull(user);
- this.token = null;
+ this(requireNonNull(user), null);
}
OriginatingCredential(OAuth2AccessToken token) {
- this.user = null;
- this.token = requireNonNull(token);
+ this(null, requireNonNull(token));
}
@Override
@@ -452,6 +448,7 @@ public String toString() {
private static final class OpenIDDerivedAuthenticationToken
extends AbstractAuthenticationToken
implements OpenIDUserAware, AlreadyDoneMarker {
+ @Serial
private static final long serialVersionUID = 970898019896708267L;
private final String who;
@@ -708,6 +705,7 @@ void apply(int userId) {
@Immutable
static final class CollabratoryAuthority extends SimpleGrantedAuthority {
+ @Serial
private static final long serialVersionUID = 4964366746649162092L;
private final String collabratory;
@@ -724,6 +722,7 @@ String getCollabratory() {
@Immutable
static final class OrganisationAuthority extends SimpleGrantedAuthority {
+ @Serial
private static final long serialVersionUID = 8260068770503054502L;
private final String organisation;
@@ -847,29 +846,19 @@ public void mapAuthorities(OidcUserAuthority user,
mapAuthorities("userinfo", user.getUserInfo(), ga);
}
+ /**
+ * Auth succeeded.
+ *
+ * @param userId
+ * The user ID
+ * @param trustLevel
+ * The trust level.
+ * @param passInfo
+ * The encoded password.
+ */
@Immutable
- private static final class LocalAuthResult {
- final int userId;
-
- final TrustLevel trustLevel;
-
- final String passInfo;
-
- /**
- * Auth succeeded.
- *
- * @param u
- * The user ID
- * @param t
- * The trust level.
- * @param ep
- * The encoded password.
- */
- LocalAuthResult(int u, TrustLevel t, String ep) {
- userId = u;
- trustLevel = requireNonNull(t);
- passInfo = requireNonNull(ep);
- }
+ private record LocalAuthResult(int userId, TrustLevel trustLevel,
+ String passInfo) {
}
/**
@@ -902,9 +891,9 @@ private boolean authLocalAgainstDB(String username, String password,
checkPassword(username, password, details, queries);
// Succeeded; finalize into external form
return queries.transaction(() -> {
- queries.noteLoginSuccessForUser(details.userId);
+ queries.noteLoginSuccessForUser(details.userId());
// Convert tiered trust level to grant form
- details.trustLevel.getGrants()
+ details.trustLevel().getGrants()
.forEach(authorities::add);
return true;
});
@@ -982,16 +971,16 @@ private static Optional lookUpUserDetails(String username,
* The username (now validated as existing).
* @param password
* The user-provided password that we're checking.
- * @param queries
- * How to access the DB.
* @param details
* The results of looking up the user
+ * @param queries
+ * How to access the DB.
*/
private void checkPassword(String username, String password,
LocalAuthResult details, AuthQueries queries) {
- if (!passServices.matchPassword(password, details.passInfo)) {
+ if (!passServices.matchPassword(password, details.passInfo())) {
queries.transaction(() -> {
- queries.noteLoginFailureForUser(details.userId, username);
+ queries.noteLoginFailureForUser(details.userId(), username);
log.info("login failure for {}: bad password", username);
throw new BadCredentialsException("bad password");
});
@@ -1112,16 +1101,14 @@ private void checkSubject(String username, String subject,
private void inflateGroup(GrantedAuthority ga, List collabs,
List orgs, AuthQueries queries) {
- if (ga instanceof CollabratoryAuthority) {
- var collab = (CollabratoryAuthority) ga;
+ if (ga instanceof CollabratoryAuthority collab) {
var collab1 = collab.getCollabratory();
if (queries.createGroup(collab1, COLLABRATORY,
quotaProps.getDefaultCollabQuota())) {
log.info("created collabratory '{}'", collab1);
}
collabs.add(collab.getCollabratory());
- } else if (ga instanceof OrganisationAuthority) {
- var org = (OrganisationAuthority) ga;
+ } else if (ga instanceof OrganisationAuthority org) {
var org1 = org.getOrganisation();
if (queries.createGroup(org1, ORGANISATION,
quotaProps.getDefaultOrgQuota())) {
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthenticationProvider.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthenticationProvider.java
index 98dbac5f71..3e0ad88621 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthenticationProvider.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthenticationProvider.java
@@ -19,8 +19,6 @@
import java.util.Collection;
-import javax.servlet.http.HttpServletRequest;
-
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
@@ -30,6 +28,7 @@
import com.google.errorprone.annotations.RestrictedApi;
+import jakarta.servlet.http.HttpServletRequest;
import uk.ac.manchester.spinnaker.alloc.ForTestingOnly;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/MyAuthenticationFailureHandler.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/MyAuthenticationFailureHandler.java
index edbda9d744..d3532e7fb2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/MyAuthenticationFailureHandler.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/MyAuthenticationFailureHandler.java
@@ -23,10 +23,6 @@
import java.io.IOException;
import java.time.Instant;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Role;
@@ -36,6 +32,9 @@
import com.fasterxml.jackson.databind.json.JsonMapper;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AuthProperties;
@Component
@@ -64,25 +63,9 @@ public void onAuthenticationFailure(HttpServletRequest request,
message += ": " + e.getLocalizedMessage();
}
mapper.writeValue(response.getOutputStream(),
- new AuthFailureObject(message));
+ new AuthFailureObject(message, now()));
}
- static class AuthFailureObject {
- private String message;
-
- private Instant timestamp;
-
- AuthFailureObject(String message) {
- this.message = message;
- this.timestamp = now();
- }
-
- public String getMessage() {
- return message;
- }
-
- public Instant getTimestamp() {
- return timestamp;
- }
+ record AuthFailureObject(String message, Instant timestamp) {
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/PasswordServices.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/PasswordServices.java
index 2a489449c2..bccdbc1881 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/PasswordServices.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/PasswordServices.java
@@ -20,12 +20,12 @@
import java.security.SecureRandom;
-import javax.annotation.PostConstruct;
-
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
+import jakarta.annotation.PostConstruct;
+
/**
* Misc services related to password handling.
*
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Permit.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Permit.java
index 55b202d969..08c634b1a3 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Permit.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Permit.java
@@ -24,6 +24,7 @@
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
+import java.io.Serial;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
@@ -59,7 +60,7 @@ public final class Permit {
* @param context
* The originating security context.
*/
- public Permit(javax.ws.rs.core.SecurityContext context) {
+ public Permit(jakarta.ws.rs.core.SecurityContext context) {
authorities = STDAUTH.stream().filter(context::isUserInRole)
.map(SimpleGrantedAuthority::new).collect(toUnmodifiableList());
admin = is(authorities, GRANT_ADMIN);
@@ -189,6 +190,7 @@ public void setAuthenticated(boolean isAuthenticated) {
}
}
+ @Serial
private void writeObject(ObjectOutputStream out)
throws NotSerializableException {
throw new NotSerializableException("not actually serializable");
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SecurityConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SecurityConfig.java
index 5b1132abaf..dc03608587 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SecurityConfig.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SecurityConfig.java
@@ -55,7 +55,7 @@
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.GrantedAuthority;
@@ -92,7 +92,7 @@
*/
@EnableWebSecurity
@Role(ROLE_APPLICATION)
-@EnableGlobalMethodSecurity(prePostEnabled = true)
+@EnableMethodSecurity(prePostEnabled = true)
@UsedInJavadocOnly(PreAuthorize.class)
public class SecurityConfig {
private static final Logger log = getLogger(SecurityConfig.class);
@@ -215,13 +215,13 @@ private String oidcPath(String suffix) {
* If anything goes wrong with setting up.
*/
private void defineAccessPolicy(HttpSecurity http) throws Exception {
- http.authorizeRequests()
+ http.authorizeHttpRequests()
// General metadata pages require ADMIN access
- .antMatchers(urlMaker.serviceUrl("info*"),
+ .requestMatchers(urlMaker.serviceUrl("info*"),
urlMaker.serviceUrl("info/**"))
.hasRole("ADMIN")
// Login process and static resources are available to all
- .antMatchers(urlMaker.systemUrl("login*"),
+ .requestMatchers(urlMaker.systemUrl("login*"),
urlMaker.systemUrl("perform_*"), oidcPath("**"),
urlMaker.systemUrl("error"),
urlMaker.systemUrl("resources/*"))
@@ -409,9 +409,8 @@ GrantedAuthoritiesMapper userAuthoritiesMapper() {
* returns each scope as a GrantedAuthority, which we don't care
* about.
*/
- if (authority instanceof OidcUserAuthority) {
- localAuthProvider.mapAuthorities(
- (OidcUserAuthority) authority, mappedAuthorities);
+ if (authority instanceof OidcUserAuthority a) {
+ localAuthProvider.mapAuthorities(a, mappedAuthorities);
}
mappedAuthorities.add(authority);
});
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SimpleGrantedAuthority.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SimpleGrantedAuthority.java
index c871dcaf1f..3f5de355eb 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SimpleGrantedAuthority.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SimpleGrantedAuthority.java
@@ -15,15 +15,22 @@
*/
package uk.ac.manchester.spinnaker.alloc.security;
+import java.io.Serial;
+
import org.springframework.security.core.GrantedAuthority;
import com.google.errorprone.annotations.Immutable;
+import uk.ac.manchester.spinnaker.alloc.security.LocalAuthProviderImpl.CollabratoryAuthority;
+import uk.ac.manchester.spinnaker.alloc.security.LocalAuthProviderImpl.OrganisationAuthority;
+
/**
* Contains a single basic role grant.
*/
@Immutable
-class SimpleGrantedAuthority implements GrantedAuthority {
+sealed class SimpleGrantedAuthority implements GrantedAuthority
+ permits CollabratoryAuthority, OrganisationAuthority {
+ @Serial
private static final long serialVersionUID = 7765648523730760900L;
private final String role;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Token.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Token.java
index 36072cffae..e0a3085e6a 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Token.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Token.java
@@ -15,28 +15,23 @@
*/
package uk.ac.manchester.spinnaker.alloc.security;
-import java.io.Serializable;
-
-import javax.servlet.http.HttpSession;
-
import org.springframework.security.core.Authentication;
+import jakarta.servlet.http.HttpSession;
+
/**
* A saved authentication token. Categorically only ever valid in the session
* for which it was created; if the session changes, it cannot be reused.
*
* @author Donal Fellows
+ * @param id
+ * The session ID
+ * @param auth
+ * The authentication token
*/
-final class Token implements Serializable {
- private static final long serialVersionUID = -439034988839648948L;
-
- private final String id;
-
- private final Authentication auth;
-
+record Token(String id, Authentication auth) {
Token(HttpSession s, Authentication a) {
- this.auth = a;
- this.id = s.getId();
+ this(s.getId(), a);
}
boolean isValid(HttpSession s) {
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Utils.java
index 0b287a1f1e..1a86c030c7 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Utils.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Utils.java
@@ -73,8 +73,8 @@ public static X509TrustManager trustManager(KeyStore truststore)
var tmf = TrustManagerFactory.getInstance(getDefaultAlgorithm());
tmf.init(truststore);
for (var tm : tmf.getTrustManagers()) {
- if (tm instanceof X509TrustManager) {
- return (X509TrustManager) tm;
+ if (tm instanceof X509TrustManager x509tm) {
+ return x509tm;
}
}
return null;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/BackgroundSupport.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/BackgroundSupport.java
index afca0083a4..1e397fe237 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/BackgroundSupport.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/BackgroundSupport.java
@@ -19,12 +19,11 @@
import java.util.concurrent.Executor;
-import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.core.Response;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.core.Response;
import uk.ac.manchester.spinnaker.alloc.security.Permit;
import uk.ac.manchester.spinnaker.alloc.web.RequestFailedException.NotFound;
import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobRequest.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobRequest.java
index 14b19aab51..caf912fb4b 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobRequest.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobRequest.java
@@ -20,17 +20,17 @@
import java.time.Duration;
import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.AssertFalse;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.PositiveOrZero;
-
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.errorprone.annotations.Keep;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.AssertFalse;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.PositiveOrZero;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidCabinetNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidFrameNumber;
@@ -45,93 +45,73 @@
* A request to create a job.
*
* @author Donal Fellows
+ * @param owner
+ * Who owns the job. Ignored when the job is submitted by a
+ * non-admin.
+ * @param group
+ * What group will the job be accounted against; the owner
+ * must be a member of the group. If {@code null}, the
+ * single group that the owner is a member of will be used (with it
+ * being an error for that to not exist or not be unique). Only one
+ * of group, {@link #nmpiCollab} or {@link #nmpiJobId} must be
+ * non-{@code null}, but all can be {@code null}.
+ * @param nmpiCollab
+ * Which NMPI Collab the job will be accounted against; the owner
+ * must be a member of the Collab. A session will be created
+ * in the Collab and this will be accounted against. Only one of
+ * {@link #group}, nmpiCollab or {@link #nmpiJobId} must be
+ * non-{@code null}, but all can be {@code null}.
+ * @param nmpiJobId
+ * Which NMPI Job the job will be accounted against; the owner
+ * must be able to update the NMPI Job. Only the quota of
+ * the NMPI Job will be updated at the end of the job, as will the
+ * local quota of the Collab of the NMPI Job. Only one of
+ * {@link #group}, {@link #nmpiCollab} or nmpiJobId must be
+ * non-{@code null}, but all can be {@code null}.
+ * @param keepaliveInterval
+ * How long after a keepalive message will the job be auto-deleted?
+ * Required. Must be between 30 and 300 seconds.
+ * @param numBoards
+ * The number of boards to allocate. May be {@code null} to either
+ * use the default (1) or to let one of the other selectors
+ * ({@link #dimensions}, {@link #board}) make the choice.
+ * @param dimensions
+ * The dimensions of rectangle of triads of boards to allocate. May
+ * be {@code null} to let one of the other selectors
+ * ({@link #numBoards}, {@link #board}) make the choice.
+ * @param board
+ * The specific board to allocate. May be {@code null} to let one of
+ * the other selectors ({@link #numBoards}, {@link #dimensions}) make
+ * the choice.
+ * @param machineName
+ * Which machine to allocate on. This and {@link #tags} are mutually
+ * exclusive, but at least one must be given.
+ * @param tags
+ * The tags to select which machine to allocate on. This and
+ * {@link #machineName} are mutually exclusive, but at least one must
+ * be given.
+ * @param maxDeadBoards
+ * The maximum number of dead boards allowed in a rectangular
+ * allocation. Note that the allocation engine might increase this if
+ * it decides to overallocate. Defaults to {@code 0}.
*/
-@SuppressWarnings("checkstyle:visibilitymodifier")
-public class CreateJobRequest {
- /**
- * Who owns the job. Ignored when the job is submitted by a non-admin.
- */
- public String owner;
-
- /**
- * What group will the job be accounted against; the owner must be
- * a member of the group. If {@code null}, the single group that the owner
- * is a member of will be used (with it being an error for that to not exist
- * or not be unique). Only one of group, {@link #nmpiCollab} or
- * {@link #nmpiJobId} must be {@code non-null}, but all can be {@code null}.
- */
- public String group;
-
- /**
- * Which NMPI Collab the job will be accounted against; the owner
- * must be a member of the Collab. A session will be created in
- * the Collab and this will be accounted against. Only one of
- * {@link #group}, nmpiCollab or {@link #nmpiJobId} must be
- * {@code non-null}, but all can be {@code null}.
- */
- public String nmpiCollab;
-
- /**
- * Which NMPI Job the job will be accounted against; the owner must
- * be able to update the NMPI Job. Only the quota of the NMPI Job will be
- * updated at the end of the job, as will the local quota of the Collab of
- * the NMPI Job. Only one of {@link #group}, {@link #nmpiCollab} or
- * nmpiJobId must be {@code non-null}, but all can be {@code null}.
- */
- public Integer nmpiJobId;
-
- /**
- * How long after a keepalive message will the job be auto-deleted?
- * Required. Must be between 30 and 300 seconds.
- */
- @NotNull(message = "keepalive-interval is required")
- public Duration keepaliveInterval;
-
- /**
- * The number of boards to allocate. May be {@code null} to either use the
- * default (1) or to let one of the other selectors ({@link #dimensions},
- * {@link #board}) make the choice.
- */
- @Positive(message = "number of boards must be at least 1 if given")
- public Integer numBoards;
-
- /**
- * The dimensions of rectangle of triads of boards to allocate. May be
- * {@code null} to let one of the other selectors ({@link #numBoards},
- * {@link #board}) make the choice.
- */
- @Valid
- public Dimensions dimensions;
-
- /**
- * The specific board to allocate. May be {@code null} to let one of the
- * other selectors ({@link #numBoards}, {@link #dimensions}) make the
- * choice.
- */
- @Valid
- public SpecificBoard board;
-
- /**
- * Which machine to allocate on. This and {@link #tags} are mutually
- * exclusive, but at least one must be given.
- */
- public String machineName;
-
- /**
- * The tags to select which machine to allocate on. This and
- * {@link #machineName} are mutually exclusive, but at least one must be
- * given.
- */
- public List<@NotBlank(message = "tags must not be blank") String> tags;
-
- /**
- * The maximum number of dead boards allowed in a rectangular allocation.
- * Note that the allocation engine might increase this if it decides to
- * overallocate. Defaults to {@code 0}.
- */
- @PositiveOrZero(message = "max-dead-boards may not be negative")
- public Integer maxDeadBoards;
-
+public record CreateJobRequest(@JsonProperty String owner,
+ @JsonProperty String group,
+ @JsonProperty("nmpi-collab") String nmpiCollab,
+ @Positive(message = "negative NMPI job IDs are unsupported") //
+ @JsonProperty("nmpi-job-id") Integer nmpiJobId,
+ @JsonProperty("keepalive-interval")
+ @NotNull(message = "keepalive-interval is "
+ + "required") Duration keepaliveInterval,
+ @JsonProperty("num-boards") @Positive(message = "number of boards "
+ + "must be at least 1 if given") Integer numBoards,
+ @JsonProperty @Valid Dimensions dimensions,
+ @JsonProperty @Valid SpecificBoard board,
+ @JsonProperty("machine-name") String machineName,
+ @JsonProperty List<@NotBlank(//
+ message = "tags must not be blank") String> tags,
+ @JsonProperty("max-dead-boards") @PositiveOrZero(message = //
+ "max-dead-boards may not be negative") Integer maxDeadBoards) {
// Extended validation
@Keep
@@ -148,6 +128,20 @@ private boolean isMachineNameInsane() {
return nonNull(machineName) && machineName.isBlank();
}
+ @Keep
+ @JsonIgnore
+ @AssertFalse(message = "group, if given, must be non-blank")
+ private boolean isGroupInsane() {
+ return nonNull(group) && group.isBlank();
+ }
+
+ @Keep
+ @JsonIgnore
+ @AssertFalse(message = "nmpi-collab, if given, must be non-blank")
+ private boolean isCollabInsane() {
+ return nonNull(nmpiCollab) && nmpiCollab.isBlank();
+ }
+
@Keep
@JsonIgnore
@AssertTrue(
@@ -163,6 +157,24 @@ private boolean isOverLocated() {
return count <= 1;
}
+ @Keep
+ @JsonIgnore
+ @AssertTrue(message = "only at most one of group, nmpi-collab and "
+ + "nmpi-job-id can be given")
+ private boolean isGroupLocatableInAtMostOneWayOnly() {
+ int count = 0;
+ if (nonNull(group)) {
+ count++;
+ }
+ if (nonNull(nmpiCollab)) {
+ count++;
+ }
+ if (nonNull(nmpiJobId)) {
+ count++;
+ }
+ return count <= 1;
+ }
+
private static final Duration MIN_KEEPALIVE = Duration.parse("PT30S");
private static final Duration MAX_KEEPALIVE = Duration.parse("PT300S");
@@ -180,47 +192,41 @@ private boolean isKeepaliveIntervalInRange() {
&& keepaliveInterval.compareTo(MIN_KEEPALIVE) >= 0);
}
- /** Describes a request for an allocation of given dimensions. */
- public static class Dimensions {
- /** The width of the rectangle of boards to allocate, in triads. */
- @ValidTriadWidth
- public int width;
-
- /** The height of the rectangle of boards to allocate, in triads. */
- @ValidTriadHeight
- public int height;
+ /**
+ * Describes a request for an allocation of given dimensions.
+ *
+ * @param width
+ * The width of the rectangle of boards to allocate, in triads.
+ * @param height
+ * The height of the rectangle of boards to allocate, in triads.
+ */
+ public record Dimensions(@ValidTriadWidth int width,
+ @ValidTriadHeight int height) {
}
- /** Describes a request for a specific board. */
- public static class SpecificBoard {
- /** The X triad coordinate of the board. */
- @ValidTriadX
- public Integer x;
-
- /** The Y triad coordinate of the board. */
- @ValidTriadY
- public Integer y;
-
- /** The Z triad coordinate of the board. */
- @ValidTriadZ
- public Integer z;
-
- /** The physical cabinet number of the board. */
- @ValidCabinetNumber
- public Integer cabinet;
-
- /** The physical frame number of the board. */
- @ValidFrameNumber
- public Integer frame;
-
- /** The physical board number of the board. */
- @ValidBoardNumber
- public Integer board;
-
- /** The IP address of the board. */
- @IPAddress(nullOK = true, message = "address must be an IP address")
- public String address;
-
+ /**
+ * Describes a request for a specific board.
+ *
+ * @param x
+ * The X triad coordinate of the board.
+ * @param y
+ * The Y triad coordinate of the board.
+ * @param z
+ * The Z triad coordinate of the board.
+ * @param cabinet
+ * The physical cabinet number of the board.
+ * @param frame
+ * The physical frame number of the board.
+ * @param board
+ * The physical board number of the board.
+ * @param address
+ * The IP address of the board.
+ */
+ public record SpecificBoard(@ValidTriadX Integer x, @ValidTriadY Integer y,
+ @ValidTriadZ Integer z, @ValidCabinetNumber Integer cabinet,
+ @ValidFrameNumber Integer frame, @ValidBoardNumber Integer board,
+ @IPAddress(nullOK = true, message = "address must be "
+ + "an IP address") String address) {
@JsonIgnore
private boolean isTriadValid() {
return nonNull(x) && nonNull(y) && nonNull(z);
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobResponse.java
index d6704b993c..cda8de87ee 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobResponse.java
@@ -19,29 +19,25 @@
import java.net.URI;
-import javax.ws.rs.core.UriInfo;
-
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.errorprone.annotations.Immutable;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI;
/**
* Describes a newly-created job.
*
* @author Donal Fellows
+ * @param jobId
+ * The ID of the job. Probably should be ignored.
+ * @param jobRef
+ * The link to the job. Clients should not make this themselves.
*/
@Immutable
-public class CreateJobResponse {
- /** The ID of the job. Probably should be ignored. */
- public final int jobId;
-
- /** The link to the job. Clients should not make this themselves. */
- @JsonInclude(NON_NULL)
- public final URI jobRef;
-
+public record CreateJobResponse(int jobId, @JsonInclude(NON_NULL) URI jobRef) {
CreateJobResponse(SpallocAPI.Job j, UriInfo ui) {
- jobId = j.getId();
- jobRef = ui.getRequestUriBuilder().path("{id}").build(j.getId());
+ this(j.getId(),
+ ui.getRequestUriBuilder().path("{id}").build(j.getId()));
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportRequest.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportRequest.java
index b513a37f02..c3f6ee6551 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportRequest.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportRequest.java
@@ -19,13 +19,12 @@
import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotBlank;
-
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.errorprone.annotations.Keep;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.NotBlank;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidCabinetNumber;
@@ -39,55 +38,43 @@
* A request to report an issue with some boards.
*
* @author Donal Fellows
+ * @param issue
+ * What the problem is believed to be.
+ * @param boards
+ * Describes the boards that have the issue.
*/
-@SuppressWarnings("checkstyle:visibilitymodifier")
-public class IssueReportRequest {
- /** What the problem is believed to be. */
- @NotBlank(message = "an issue description must be given")
- public String issue;
-
- /** Describes the boards that have the issue. */
- public List<@Valid ReportedBoard> boards;
-
- /** Describes a board that has an issue. */
- public static class ReportedBoard {
-
- /** The machine containing the board. */
- @NotBlank
- public String machine;
-
- /** The location of the chip within the reporting allocation. */
- @Valid
- public ChipLocation chip;
-
- /** The X triad coordinate of the board. */
- @ValidTriadX
- public Integer x;
-
- /** The Y triad coordinate of the board. */
- @ValidTriadY
- public Integer y;
-
- /** The Z triad coordinate of the board. */
- @ValidTriadZ
- public Integer z;
-
- /** The physical cabinet number of the board. */
- @ValidCabinetNumber
- public Integer cabinet;
-
- /** The physical frame number of the board. */
- @ValidFrameNumber
- public Integer frame;
-
- /** The physical board number of the board. */
- @ValidBoardNumber
- public Integer board;
-
- /** The IP address of the board. */
- @IPAddress(nullOK = true, message = "address must be an IP address")
- public String address;
-
+public record IssueReportRequest(
+ @NotBlank(message = "an issue description must be given") String issue,
+ List<@Valid ReportedBoard> boards) {
+ /**
+ * Describes a board that has an issue.
+ *
+ * @param machine
+ * The machine containing the board.
+ * @param chip
+ * The location of the chip within the reporting allocation.
+ * @param x
+ * The X triad coordinate of the board.
+ * @param y
+ * The Y triad coordinate of the board.
+ * @param z
+ * The Z triad coordinate of the board.
+ * @param cabinet
+ * The physical cabinet number of the board.
+ * @param frame
+ * The physical frame number of the board.
+ * @param board
+ * The physical board number of the board.
+ * @param address
+ * The IP address of the board.
+ */
+ public record ReportedBoard(
+ @NotBlank String machine, @Valid ChipLocation chip,
+ @ValidTriadX Integer x, @ValidTriadY Integer y,
+ @ValidTriadZ Integer z, @ValidCabinetNumber Integer cabinet,
+ @ValidFrameNumber Integer frame, @ValidBoardNumber Integer board,
+ @IPAddress(nullOK = true, message = "address must be "
+ + "an IP address") String address) {
@JsonIgnore
private boolean isChipValid() {
return nonNull(chip);
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportResponse.java
index 46448571a6..cbca7092ad 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/IssueReportResponse.java
@@ -21,16 +21,10 @@
* Describes whether an issue with a board was reported successfully.
*
* @author Donal Fellows
+ * @param action
+ * What immediate action will be taken. Typically "{@code noted}" or
+ * "{@code taken out of service}".
*/
@Immutable
-public class IssueReportResponse {
- /**
- * What immediate action will be taken. Typically "{@code noted}" or
- * "{@code taken out of service}".
- */
- public final String action;
-
- IssueReportResponse(String action) {
- this.action = action;
- }
+public record IssueReportResponse(String action) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/JobStateResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/JobStateResponse.java
index dcf3b3e399..e8ef8c867f 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/JobStateResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/JobStateResponse.java
@@ -26,13 +26,12 @@
import java.net.URI;
import java.time.Instant;
-import javax.ws.rs.core.UriInfo;
-
import org.springframework.dao.DataAccessException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.json.JsonMapper;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Job;
import uk.ac.manchester.spinnaker.alloc.model.JobState;
import uk.ac.manchester.spinnaker.alloc.proxy.SpinWSHandler;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ListJobsResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ListJobsResponse.java
index 3aee474922..21527cbf43 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ListJobsResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ListJobsResponse.java
@@ -22,10 +22,9 @@
import java.net.URI;
import java.util.List;
-import javax.ws.rs.core.UriInfo;
-
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Jobs;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinePower.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinePower.java
index d35cb5c5ac..7b2720bea0 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinePower.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinePower.java
@@ -15,11 +15,10 @@
*/
package uk.ac.manchester.spinnaker.alloc.web;
-import javax.validation.constraints.NotNull;
-
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.errorprone.annotations.Immutable;
+import jakarta.validation.constraints.NotNull;
import uk.ac.manchester.spinnaker.alloc.model.PowerState;
/**
@@ -27,26 +26,10 @@
* of it allocated to a job), or a state that the user wants us to switch into.
*
* @author Donal Fellows
+ * @param power the machine power state
*/
@Immutable
-public class MachinePower {
- @NotNull(message = "power must be specified")
- private final PowerState power;
-
- /**
- * Make an instance.
- *
- * @param power
- * the machine power state
- */
- public MachinePower(
- @JsonProperty(value = "power", defaultValue = "OFF")
- PowerState power) {
- this.power = power;
- }
-
- /** @return the machine power state */
- public PowerState getPower() {
- return power;
- }
+public record MachinePower(
+ @JsonProperty(value = "power", defaultValue = "OFF")
+ @NotNull(message = "power must be specified") PowerState power) {
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachineResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachineResponse.java
index 51c74b5405..ab0b3f1498 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachineResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachineResponse.java
@@ -25,10 +25,9 @@
import java.net.URI;
import java.util.List;
-import javax.ws.rs.core.UriInfo;
-
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI;
import uk.ac.manchester.spinnaker.alloc.model.BoardCoords;
import uk.ac.manchester.spinnaker.alloc.model.DownLink;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinesResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinesResponse.java
index 54e0973ef2..b5d7dc91a9 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinesResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinesResponse.java
@@ -15,16 +15,14 @@
*/
package uk.ac.manchester.spinnaker.alloc.web;
+import static java.util.stream.Collectors.toUnmodifiableList;
import static uk.ac.manchester.spinnaker.utils.CollectionUtils.copy;
import java.net.URI;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-
-import javax.ws.rs.core.UriInfo;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Machine;
import uk.ac.manchester.spinnaker.alloc.model.BoardCoords;
import uk.ac.manchester.spinnaker.alloc.model.DownLink;
@@ -34,59 +32,48 @@
* {@link BriefMachineDescription}s.
*
* @author Donal Fellows
+ * @param machines
+ * The list of machines known to the service.
*/
-public final class MachinesResponse {
+public record MachinesResponse(List machines) {
/**
* A brief, summary description of a machine.
*
* @author Donal Fellows
+ * @param name
+ * The name of the machine.
+ * @param tags
+ * The tags of the machine.
+ * @param uri
+ * The URI to the machine.
+ * @param width
+ * The width of the machine, in triads.
+ * @param height
+ * The height of the machine, in triads.
+ * @param deadBoards
+ * The dead boards on the machine.
+ * @param deadLinks
+ * The dead links on the machine.
*/
- public static final class BriefMachineDescription {
- /** The name of the machine. */
- public final String name;
-
- /** The tags of the machine. */
- public final List tags;
-
- /** The URI to the machine. */
- public final URI uri;
-
- /** The width of the machine, in triads. */
- public final int width;
-
- /** The height of the machine, in triads. */
- public final int height;
-
- /** The dead boards on the machine. */
- public final List deadBoards;
-
- /** The dead links on the machine. */
- public final List deadLinks;
-
- private BriefMachineDescription(String name, URI uri, int width,
- int height, Set tags, List deadBoards,
- List deadLinks) {
- this.name = name;
- this.uri = uri;
- this.width = width;
- this.height = height;
- this.tags = List.copyOf(tags);
- this.deadBoards = copy(deadBoards);
- this.deadLinks = copy(deadLinks);
- }
+ public record BriefMachineDescription(String name, List tags,
+ URI uri, int width, int height, List deadBoards,
+ List deadLinks) {
}
- /** The list of machines known to the service. */
- public final List machines;
-
MachinesResponse(Map machines, UriInfo ui) {
- var mlist = new ArrayList(machines.size());
+ this(makeBriefDescriptions(machines, ui));
+ }
+
+ private static List makeBriefDescriptions(
+ Map machines, UriInfo ui) {
var ub = ui.getAbsolutePathBuilder().path("{name}");
- machines.forEach((name,
- machine) -> mlist.add(new BriefMachineDescription(name,
- ub.build(name), machine.getWidth(), machine.getHeight(),
- machine.getTags(), machine.getDeadBoards(),
- machine.getDownLinks())));
- this.machines = copy(mlist);
+ return machines.entrySet().stream()
+ .map(e -> new BriefMachineDescription(e.getKey(),
+ List.copyOf(e.getValue().getTags()),
+ ub.build(e.getKey()), e.getValue().getWidth(),
+ e.getValue().getHeight(),
+ copy(e.getValue().getDeadBoards()),
+ copy(e.getValue().getDownLinks())))
+ .collect(toUnmodifiableList());
}
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java
index 748cb189b0..3c6623b1e2 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java
@@ -15,27 +15,29 @@
*/
package uk.ac.manchester.spinnaker.alloc.web;
+import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN;
+import static jakarta.ws.rs.core.Response.noContent;
+import static jakarta.ws.rs.core.Response.status;
+import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
+import static jakarta.ws.rs.core.Response.Status.GONE;
+import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;
+import static jakarta.ws.rs.core.Response.Status.NO_CONTENT;
+import static jakarta.ws.rs.core.Response.Status.Family.SERVER_ERROR;
import static java.util.Objects.nonNull;
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-import static javax.ws.rs.core.Response.noContent;
-import static javax.ws.rs.core.Response.status;
-import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
-import static javax.ws.rs.core.Response.Status.GONE;
-import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
-import static javax.ws.rs.core.Response.Status.NOT_FOUND;
-import static javax.ws.rs.core.Response.Status.NO_CONTENT;
-import static javax.ws.rs.core.Response.Status.Family.SERVER_ERROR;
import static org.slf4j.LoggerFactory.getLogger;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import java.io.Serial;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
+
/**
* Thrown to indicate various sorts of problems with the service. Very much like
* a {@link WebApplicationException} except with a different handling strategy.
@@ -43,6 +45,7 @@
* @author Donal Fellows
*/
public class RequestFailedException extends RuntimeException {
+ @Serial
private static final long serialVersionUID = -7522760691720854101L;
/** The status code. */
@@ -98,8 +101,8 @@ public RequestFailedException(Throwable cause) {
*/
Response toResponse() {
var cause = getCause();
- if (cause instanceof WebApplicationException) {
- return ((WebApplicationException) cause).getResponse();
+ if (cause instanceof WebApplicationException waex) {
+ return waex.getResponse();
} else if (cause != null) {
// Be careful about what bits are extracted from message
var cls = cause.getClass().getName().replaceFirst("^.*[.]", "")
@@ -133,6 +136,7 @@ private void log(Logger log) {
/** A resource is no longer believed to exist. */
public static class ItsGone extends RequestFailedException {
+ @Serial
private static final long serialVersionUID = 3774531853141947270L;
/**
@@ -146,6 +150,7 @@ public ItsGone(String message) {
/** A resource cannot be located. */
public static class NotFound extends RequestFailedException {
+ @Serial
private static final long serialVersionUID = 5991697173204757030L;
/**
@@ -169,6 +174,7 @@ public NotFound(String message, Throwable cause) {
/** The client provided bad arguments in a request. */
public static class BadArgs extends RequestFailedException {
+ @Serial
private static final long serialVersionUID = 7916573155067333350L;
/**
@@ -182,6 +188,7 @@ public BadArgs(String message) {
/** The response is empty. */
public static class EmptyResponse extends RequestFailedException {
+ @Serial
private static final long serialVersionUID = -2944836034264700912L;
/** Create an instance. */
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ServiceDescription.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ServiceDescription.java
index 34eb6d662d..aa1f88c7ff 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ServiceDescription.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/ServiceDescription.java
@@ -22,13 +22,12 @@
import java.net.URI;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-
import org.springframework.security.web.csrf.CsrfToken;
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.messages.model.Version;
/**
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPI.java
index c550f9b21f..00c5e81f0c 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPI.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPI.java
@@ -16,8 +16,8 @@
package uk.ac.manchester.spinnaker.alloc.web;
import static io.swagger.v3.oas.annotations.enums.ParameterIn.PATH;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN;
import static uk.ac.manchester.spinnaker.alloc.security.SecurityConfig.IS_READER;
import static uk.ac.manchester.spinnaker.alloc.security.SecurityConfig.IS_USER;
import static uk.ac.manchester.spinnaker.alloc.web.DocConstants.T_JOB;
@@ -41,29 +41,6 @@
import static uk.ac.manchester.spinnaker.alloc.web.WebServiceComponentNames.SERV;
import static uk.ac.manchester.spinnaker.alloc.web.WebServiceComponentNames.WAIT;
-import javax.servlet.http.HttpServletRequest;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.PositiveOrZero;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.container.Suspended;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-
import org.apache.cxf.jaxrs.model.wadl.Description;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -75,6 +52,28 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.PositiveOrZero;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.container.Suspended;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.machine.ValidX;
import uk.ac.manchester.spinnaker.machine.ValidY;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPIImplBuilder.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPIImplBuilder.java
index 0ac02082c9..ec0d866250 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPIImplBuilder.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPIImplBuilder.java
@@ -15,19 +15,15 @@
*/
package uk.ac.manchester.spinnaker.alloc.web;
+import static jakarta.ws.rs.core.Response.accepted;
+import static jakarta.ws.rs.core.Response.noContent;
import static java.util.Objects.isNull;
-import static javax.ws.rs.core.Response.accepted;
-import static javax.ws.rs.core.Response.noContent;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.beans.factory.config.BeanDefinition.ROLE_APPLICATION;
import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT;
import java.util.Optional;
-import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -37,6 +33,9 @@
import com.fasterxml.jackson.databind.json.JsonMapper;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.SpallocProperties;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.BoardLocation;
@@ -230,7 +229,7 @@ public void setMachinePower(MachinePower reqBody,
}
bgAction(response, permit, () -> {
j.access(caller);
- allocation().setPower(reqBody.getPower());
+ allocation().setPower(reqBody.power());
return accepted().build();
});
}
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceImpl.java
index ce62c6d230..e7b7530759 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceImpl.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceImpl.java
@@ -21,11 +21,11 @@
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.toList;
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-import static javax.ws.rs.core.Response.created;
-import static javax.ws.rs.core.Response.ok;
-import static javax.ws.rs.core.Response.status;
-import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN;
+import static jakarta.ws.rs.core.Response.created;
+import static jakarta.ws.rs.core.Response.ok;
+import static jakarta.ws.rs.core.Response.status;
+import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.CreateBoard.address;
import static uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.CreateBoard.physical;
@@ -38,12 +38,12 @@
import java.util.HashMap;
import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Path;
-import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.container.AsyncResponse;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.springframework.beans.factory.ObjectProvider;
@@ -214,9 +214,11 @@ private static String trim(String str) {
/**
* Select one of the ways to create a job based on the request parameters.
- * Note this will pick the first non-null of (group, nmpiCollabId,
- * nmpiJobId) from req to determine the spalloc call to make (also
- * acceptable if all are null).
+ *
+ * Note that this will pick the first non-{@code null} of
+ * (group, nmpiCollabId, nmpiJobId) from req to determine the spalloc call
+ * to make (also acceptable if all are {@code null}). Validation
+ * should ensure that at most one of those is non-{@code null}.
*
* @param req
* The request details.
@@ -228,50 +230,33 @@ private static String trim(String str) {
*/
private Optional createJob(CreateJobRequest req,
CreateDescriptor crds) throws JsonProcessingException {
- if (!isNull(req.group)) {
- return core.createJobInGroup(trim(req.owner), trim(req.group), crds,
- req.machineName, req.tags, req.keepaliveInterval,
- mapper.writeValueAsBytes(req));
- }
- if (!isNull(req.nmpiCollab)) {
- return core.createJobInCollabSession(trim(req.owner),
- trim(req.nmpiCollab), crds,
- req.machineName, req.tags, req.keepaliveInterval,
- mapper.writeValueAsBytes(req));
- }
- if (!isNull(req.nmpiJobId)) {
- return core.createJobForNMPIJob(trim(req.owner),
- req.nmpiJobId, crds,
- req.machineName, req.tags, req.keepaliveInterval,
+ if (!isNull(req.group())) {
+ return core.createJobInGroup(trim(req.owner()), trim(req.group()),
+ crds, req.machineName(), req.tags(),
+ req.keepaliveInterval(), mapper.writeValueAsBytes(req));
+ } else if (!isNull(req.nmpiCollab())) {
+ return core.createJobInCollabSession(trim(req.owner()),
+ trim(req.nmpiCollab()), crds, req.machineName(), req.tags(),
+ req.keepaliveInterval(), mapper.writeValueAsBytes(req));
+ } else if (!isNull(req.nmpiJobId())) {
+ return core.createJobForNMPIJob(trim(req.owner()), req.nmpiJobId(),
+ crds, req.machineName(), req.tags(),
+ req.keepaliveInterval(), mapper.writeValueAsBytes(req));
+ } else {
+ return core.createJob(trim(req.owner()), crds, req.machineName(),
+ req.tags(), req.keepaliveInterval(),
mapper.writeValueAsBytes(req));
}
- return core.createJob(trim(req.owner), crds,
- req.machineName, req.tags, req.keepaliveInterval,
- mapper.writeValueAsBytes(req));
}
@Override
public void createJob(CreateJobRequest req, UriInfo ui,
SecurityContext security, AsyncResponse response) {
- var crds = validateAndApplyDefaultsToJobRequest(req, security);
-
- // Ensure we only have at most one "group" specifier (0 also fine).
- var nonNullGroups = 0;
- var items = new Object[] {
- req.group, req.nmpiCollab, req.nmpiJobId
- };
- for (Object item : items) {
- if (!isNull(item)) {
- nonNullGroups += 1;
- }
- }
- if (nonNullGroups > 1) {
- response.resume(status(BAD_REQUEST).type(TEXT_PLAIN).entity(
- "At most one of group, nmpiCollabId or nmpiJobId"
- + " can be specified").build());
- }
+ var r = validateCreateJobNonSizeAttrs(req, security);
+ var crds = validateAndApplyDefaultsToJobRequest(r, security);
+
bgAction(response, () -> ifElse(
- createJob(req, crds),
+ createJob(r, crds),
job -> created(ui.getRequestUriBuilder().path("{id}")
.build(job.getId()))
.entity(new CreateJobResponse(job, ui)).build(),
@@ -280,86 +265,96 @@ public void createJob(CreateJobRequest req, UriInfo ui,
.entity("out of quota").build()));
}
- private CreateDescriptor validateAndApplyDefaultsToJobRequest(
- CreateJobRequest req, SecurityContext security) throws BadArgs {
+ private CreateJobRequest validateCreateJobNonSizeAttrs(CreateJobRequest req,
+ SecurityContext security) {
if (isNull(req)) {
throw new BadArgs("request must be supplied");
}
+ var owner = req.owner();
if (!security.isUserInRole("ADMIN")
&& !security.isUserInRole("NMPI_EXEC")
- && !isNull(req.owner) && !req.owner.isBlank()) {
+ && !isNull(owner) && !owner.isBlank()) {
throw new BadArgs("Only admin and NMPI users can specify an owner");
}
- if (isNull(req.owner) || req.owner.isBlank()) {
- req.owner = security.getUserPrincipal().getName();
+ if (isNull(owner) || owner.isBlank()) {
+ owner = security.getUserPrincipal().getName();
}
- if (isNull(req.owner) || req.owner.isBlank()) {
+ if (isNull(owner) || owner.isBlank()) {
throw new BadArgs(
"request must be connected to an identified owner");
}
- req.owner = req.owner.strip();
+ owner = owner.strip();
var ka = properties.getKeepalive();
- if (isNull(req.keepaliveInterval)
- || req.keepaliveInterval.compareTo(ka.getMin()) < 0) {
+ if (isNull(req.keepaliveInterval())
+ || req.keepaliveInterval().compareTo(ka.getMin()) < 0) {
throw new BadArgs(
"keepalive interval must be at least " + ka.getMin());
}
- if (req.keepaliveInterval.compareTo(ka.getMax()) > 0) {
+ if (req.keepaliveInterval().compareTo(ka.getMax()) > 0) {
throw new BadArgs(
"keepalive interval must be no more than " + ka.getMax());
}
- if (isNull(req.tags)) {
- req.tags = new ArrayList<>();
- if (isNull(req.machineName)) {
- req.tags.add("default");
+ var tags = req.tags();
+ if (isNull(tags)) {
+ tags = new ArrayList<>();
+ if (isNull(req.machineName())) {
+ tags.add("default");
}
}
- if (nonNull(req.machineName) && !req.tags.isEmpty()) {
+ if (nonNull(req.machineName()) && !tags.isEmpty()) {
throw new BadArgs(
"must not specify machine name and tags together");
}
- if (isNull(req.maxDeadBoards)) {
- req.maxDeadBoards = 0;
- } else if (req.maxDeadBoards < 0) {
+ return new CreateJobRequest(owner, req.group(), req.nmpiCollab(),
+ req.nmpiJobId(), req.keepaliveInterval(), req.numBoards(),
+ req.dimensions(), req.board(), req.machineName(), tags,
+ req.maxDeadBoards());
+ }
+
+ private CreateDescriptor validateAndApplyDefaultsToJobRequest(
+ CreateJobRequest req, SecurityContext security) throws BadArgs {
+ var maxDead = req.maxDeadBoards();
+ if (isNull(maxDead)) {
+ maxDead = 0;
+ } else if (maxDead < 0) {
throw new BadArgs(
"the maximum number of dead boards must not be negative");
}
- if (nonNull(req.numBoards)) {
- return new CreateNumBoards(req.numBoards, req.maxDeadBoards);
- } else if (nonNull(req.dimensions)) {
- if (nonNull(req.board)) {
+ if (nonNull(req.numBoards())) {
+ return new CreateNumBoards(req.numBoards(), maxDead);
+ } else if (nonNull(req.dimensions())) {
+ var size = req.dimensions();
+ var specific = req.board();
+ if (nonNull(specific)) {
// Both dimensions AND board; rooted rectangle
- if (nonNull(req.board.x)) {
- return new CreateDimensionsAt(req.dimensions.width,
- req.dimensions.height, req.board.x, req.board.y,
- req.board.z, req.maxDeadBoards);
- } else if (nonNull(req.board.cabinet)) {
- return CreateDimensionsAt.physical(req.dimensions.width,
- req.dimensions.height, req.board.cabinet,
- req.board.frame, req.board.board,
- req.maxDeadBoards);
+ if (nonNull(specific.x())) {
+ return new CreateDimensionsAt(size.width(), size.height(),
+ specific.x(), specific.y(), specific.z(), maxDead);
+ } else if (nonNull(specific.cabinet())) {
+ return CreateDimensionsAt.physical(size.width(),
+ size.height(), specific.cabinet(), specific.frame(),
+ specific.board(), maxDead);
} else {
- return new CreateDimensionsAt(req.dimensions.width,
- req.dimensions.height, req.board.address,
- req.maxDeadBoards);
+ return new CreateDimensionsAt(size.width(), size.height(),
+ specific.address(), maxDead);
}
}
- return new CreateDimensions(req.dimensions.width,
- req.dimensions.height, req.maxDeadBoards);
- } else if (nonNull(req.board)) {
- if (nonNull(req.board.x)) {
- return triad(req.board.x, req.board.y, req.board.z);
- } else if (nonNull(req.board.cabinet)) {
- return physical(req.board.cabinet, req.board.frame,
- req.board.board);
+ return new CreateDimensions(size.width(), size.height(), maxDead);
+ } else if (nonNull(req.board())) {
+ var specific = req.board();
+ if (nonNull(specific.x())) {
+ return triad(specific.x(), specific.y(), specific.z());
+ } else if (nonNull(specific.cabinet())) {
+ return physical(specific.cabinet(), specific.frame(),
+ specific.board());
} else {
- return address(req.board.address);
+ return address(specific.address());
}
} else {
// It's a single board
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SubMachineResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SubMachineResponse.java
index b1a505bfbc..7b891b9621 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SubMachineResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SubMachineResponse.java
@@ -24,10 +24,9 @@
import java.net.URI;
import java.util.List;
-import javax.ws.rs.core.UriInfo;
-
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.SubMachine;
import uk.ac.manchester.spinnaker.alloc.model.ConnectionInfo;
import uk.ac.manchester.spinnaker.spalloc.messages.BoardCoordinates;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemController.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemController.java
index d5d99be3d8..82bb1540b7 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemController.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemController.java
@@ -20,10 +20,6 @@
import java.security.Principal;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.web.bind.annotation.GetMapping;
@@ -34,6 +30,9 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
import uk.ac.manchester.spinnaker.alloc.model.JobDescription;
import uk.ac.manchester.spinnaker.alloc.model.JobListEntryRecord;
import uk.ac.manchester.spinnaker.alloc.model.MachineDescription;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemControllerImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemControllerImpl.java
index 859642f9a5..de9947561d 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemControllerImpl.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SystemControllerImpl.java
@@ -43,10 +43,6 @@
import java.security.Principal;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
@@ -66,6 +62,9 @@
import com.google.errorprone.annotations.Keep;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
import uk.ac.manchester.spinnaker.alloc.ServiceConfig.URLPathMaker;
import uk.ac.manchester.spinnaker.alloc.ServiceVersion;
import uk.ac.manchester.spinnaker.alloc.admin.UserControl;
diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/WhereIsResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/WhereIsResponse.java
index d79a8034ba..01c6578ce7 100644
--- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/WhereIsResponse.java
+++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/WhereIsResponse.java
@@ -22,10 +22,9 @@
import java.net.URI;
-import javax.ws.rs.core.UriInfo;
-
import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.BoardLocation;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
import uk.ac.manchester.spinnaker.spalloc.messages.BoardCoordinates;
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql b/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql
index 0e4b7a8b85..a8a56d90a5 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql
@@ -12,6 +12,11 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Count the number of connected boards (i.e., have at least one path over
+-- enabled links to the root board of the allocation) within a rectangle of
+-- triads. The triads are taken as being full depth.
+
WITH RECURSIVE
args(machine_id, x, y, width, height) AS (
SELECT :machine_id, :x, :y, :width, :height),
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/connected_boards_at_coords.sql b/SpiNNaker-allocserv/src/main/resources/queries/connected_boards_at_coords.sql
index a1a5047a21..4b30db170f 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/connected_boards_at_coords.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/connected_boards_at_coords.sql
@@ -12,6 +12,11 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Get the set of boards at some coordinates within a triad rectangle that
+-- are connected (i.e., have at least one path over enableable links within
+-- the allocation) to the root board.
+
WITH RECURSIVE
args(machine_id, x, y, z, width, height, depth) AS (
SELECT :machine_id, :x, :y, :z, :width, :height, :depth),
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_global_chip.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_global_chip.sql
index 4d426f88b8..6668fe7baa 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_global_chip.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_global_chip.sql
@@ -12,6 +12,10 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Locate a board (using a full set of coordinates) based on global chip
+-- coordinates.
+
SELECT
-- IDs
boards.board_id,
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_ip_address.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_ip_address.sql
index 010350832b..c7e407d8a8 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_ip_address.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_ip_address.sql
@@ -12,6 +12,10 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Locate a board (using a full set of coordinates) based on the IP address
+-- of its ethernet chip.
+
SELECT
-- IDs
boards.board_id,
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_job_chip.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_job_chip.sql
index 2f80db0b6f..e8977fbf90 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_job_chip.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_job_chip.sql
@@ -12,6 +12,10 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Locate a board (using a full set of coordinates) based on allocation-local
+-- chip coordinates.
+
WITH
args(job, root, x, y) AS (SELECT :job_id, :board_id, :x, :y),
-- Boards that are allocated to the job
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_logical_coords.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_logical_coords.sql
index 3723540ce9..a119190c93 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_logical_coords.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_logical_coords.sql
@@ -12,6 +12,10 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Locate a board (using a full set of coordinates) based on logical triad
+-- coordinates.
+
SELECT
-- IDs
boards.board_id,
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_physical_coords.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_physical_coords.sql
index e06824c58f..5368c712ce 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_physical_coords.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_board_by_physical_coords.sql
@@ -12,6 +12,10 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Locate a board (using a full set of coordinates) based on physical
+-- cabinet-frame-board coordinates.
+
SELECT
-- IDs
boards.board_id,
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_location.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_location.sql
deleted file mode 100644
index f3f50ce90e..0000000000
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_location.sql
+++ /dev/null
@@ -1,20 +0,0 @@
--- Copyright (c) 2021 The University of Manchester
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-
-SELECT
- x, y, z
-FROM boards
-WHERE boards.machine_id = :machine_id
- AND boards.board_id = :board_id
- AND boards.may_be_allocated;
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql
index b86d0fb96e..1a97996aa3 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql
@@ -12,6 +12,8 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+
WITH RECURSIVE
-- Name the arguments for sanity
args(width, height, machine_id, max_dead_boards) AS (
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql
index 0f0426850d..2df2aadab9 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql
@@ -12,6 +12,8 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+
WITH RECURSIVE
-- Name the arguments for sanity
args(root_id, width, height, machine_id, max_dead_boards) AS (
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql
deleted file mode 100644
index 73d3c4deaf..0000000000
--- a/SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql
+++ /dev/null
@@ -1,34 +0,0 @@
--- Copyright (c) 2021 The University of Manchester
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-
--- Get current allocation tasks
-SELECT
- job_request.req_id,
- job_request.job_id,
- job_request.num_boards,
- job_request.width,
- job_request.height,
- job_request.board_id,
- jobs.machine_id AS machine_id,
- job_request.max_dead_boards,
- machines.width AS max_width,
- machines.height AS max_height,
- jobs.job_state AS job_state,
- job_request.importance
-FROM
- job_request
- JOIN jobs USING (job_id)
- JOIN machines USING (machine_id)
-WHERE job_state = :job_state
-ORDER BY importance DESC, req_id ASC;
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql
deleted file mode 100644
index 5db92a3a23..0000000000
--- a/SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql
+++ /dev/null
@@ -1,43 +0,0 @@
--- Copyright (c) 2021 The University of Manchester
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-
--- Get the dead links of a machine; each link is described by the boards it
--- links and the directions the link goes in at each end.
-SELECT
- -- Link end 1: board coords + direction
- b1.x AS board_1_x,
- b1.y AS board_1_y,
- b1.z AS board_1_z,
- bmp1.cabinet AS board_1_c,
- bmp1.frame AS board_1_f,
- b1.board_num AS board_1_b,
- b1.address AS board_1_addr,
- dir_1,
- -- Link end 2: board coords + direction
- b2.x AS board_2_x,
- b2.y AS board_2_y,
- b2.z AS board_2_z,
- bmp2.cabinet AS board_2_c,
- bmp2.frame AS board_2_f,
- b2.board_num AS board_2_b,
- b2.address AS board_2_addr,
- dir_2
-FROM links
- JOIN boards AS b1 ON board_1 = b1.board_id
- JOIN boards AS b2 ON board_2 = b2.board_id
- JOIN bmp AS bmp1 ON bmp1.bmp_id = b1.bmp_id
- JOIN bmp AS bmp2 ON bmp2.bmp_id = b2.bmp_id
-WHERE
- b1.machine_id = :machine_id AND NOT live
-ORDER BY board_1 ASC, board_2 ASC;
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/get_jobs_with_changes.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_jobs_with_changes.sql
index 0988f16ab5..5a478b7c38 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/get_jobs_with_changes.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/get_jobs_with_changes.sql
@@ -12,6 +12,12 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
+-- --------------------------------------------------------------------------
+-- Get jobs on a machine that have changes that can be processed. This
+-- respects a machine-level policy on how long a board must be switched off
+-- before it can be switched on again, and how long a board must be switched
+-- on before it can be switched off.
+
WITH
-- Arguments and current timestamp
args(machine_id, now) AS (
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql
deleted file mode 100644
index dc70c8bdc4..0000000000
--- a/SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql
+++ /dev/null
@@ -1,34 +0,0 @@
--- Copyright (c) 2021 The University of Manchester
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-
--- Get boards with more problem reports than a critical threshold
-WITH report_counts AS (
- SELECT
- board_reports.board_id,
- COUNT(board_reports.report_id) AS num_reports
- FROM board_reports
- JOIN boards USING (board_id)
- WHERE boards.functioning != 0 -- Ignore disabled boards
- GROUP BY board_id)
-SELECT
- boards.board_id,
- report_counts.num_reports,
- boards.x,
- boards.y,
- boards.z,
- boards.address
-FROM
- report_counts
- JOIN boards USING (board_id)
-WHERE report_counts.num_reports >= :threshold;
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/issue_change_for_job.sql b/SpiNNaker-allocserv/src/main/resources/queries/issue_change_for_job.sql
deleted file mode 100644
index 9495796e9c..0000000000
--- a/SpiNNaker-allocserv/src/main/resources/queries/issue_change_for_job.sql
+++ /dev/null
@@ -1,20 +0,0 @@
--- Copyright (c) 2021 The University of Manchester
---
--- Licensed under the Apache License, Version 2.0 (the "License");
--- you may not use this file except in compliance with the License.
--- You may obtain a copy of the License at
---
--- https://www.apache.org/licenses/LICENSE-2.0
---
--- Unless required by applicable law or agreed to in writing, software
--- distributed under the License is distributed on an "AS IS" BASIS,
--- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--- See the License for the specific language governing permissions and
--- limitations under the License.
-
-INSERT INTO pending_changes(
- job_id, board_id, from_state, to_state,
- power, fpga_n, fpga_e, fpga_se, fpga_s, fpga_w, fpga_nw)
-VALUES (
- :job_id, :board_id, :from_state, :to_state,
- :power, :fpga_n, :fpga_e, :fpga_se, :fpga_s, :fpga_w, :fpga_nw);
diff --git a/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql b/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql
index 753630cb98..f56a1965dc 100644
--- a/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql
+++ b/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql
@@ -12,9 +12,14 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
-WITH
+-- --------------------------------------------------------------------------
+-- Get the links on the perimeter of the allocation to a job. The perimeter
+-- is defined as being the live links between a board that is part of the
+-- allocation and a board that is not.
+
+WITH bs AS (
-- Boards that are allocated to the job
- bs AS (SELECT board_id FROM boards WHERE allocated_job = :job_id)
+ SELECT board_id FROM boards WHERE allocated_job = :job_id)
SELECT board_1 AS board_id, dir_1 AS direction FROM links
WHERE board_1 IN (SELECT board_id FROM bs)
AND live
diff --git a/SpiNNaker-allocserv/src/main/resources/spalloc.sql b/SpiNNaker-allocserv/src/main/resources/spalloc.sql
index 656256fe14..2bc0fe9058 100644
--- a/SpiNNaker-allocserv/src/main/resources/spalloc.sql
+++ b/SpiNNaker-allocserv/src/main/resources/spalloc.sql
@@ -397,7 +397,7 @@ CREATE TABLE IF NOT EXISTS pending_changes (
CREATE TABLE IF NOT EXISTS blacklist_ops (
op_id INTEGER PRIMARY KEY AUTOINCREMENT,
- board_id INTEGER UNIQUE NOT NULL
+ board_id INTEGER NOT NULL
CONSTRAINT "blacklist_ops.board_id -> boards.board_id"
REFERENCES boards(board_id) ON DELETE RESTRICT,
op INTEGER NOT NULL, -- What we plan to do (NonBootOperations ID)
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/board.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/board.jsp
index c976340461..8de2753efa 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/board.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/board.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/createuser.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/createuser.jsp
index 903f65ff1e..b01c33bb66 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/createuser.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/createuser.jsp
@@ -1,5 +1,5 @@
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/footer.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/footer.jsp
index 732f355f57..6eb9cbf41a 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/footer.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/footer.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/groupdetails.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/groupdetails.jsp
index 1b047b694e..c223b3598f 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/groupdetails.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/groupdetails.jsp
@@ -1,8 +1,8 @@
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
+<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listgroups.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listgroups.jsp
index 08ba7da44f..f8eae583bd 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listgroups.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listgroups.jsp
@@ -1,5 +1,5 @@
<%@ page trimDirectiveWhitespaces="true" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2022 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listusers.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listusers.jsp
index 7b379ab2b0..12465a3126 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listusers.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/listusers.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/machine.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/machine.jsp
index b688bc3af1..e144d72dd6 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/machine.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/machine.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/userdetails.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/userdetails.jsp
index 264663bfc0..303017a71d 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/userdetails.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/admin/userdetails.jsp
@@ -1,6 +1,6 @@
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
+<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/basicfooter.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/basicfooter.jsp
index 5b1476364f..d1ad0751f1 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/basicfooter.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/basicfooter.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/jobdetails_obj.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/jobdetails_obj.jsp
index a86e0b695e..91cc8d4247 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/jobdetails_obj.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/jobdetails_obj.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="json" uri="http://www.atg.com/taglibs/json" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/machinedetails_obj.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/machinedetails_obj.jsp
index 4d40d08ac2..e82a7f2d85 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/machinedetails_obj.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/data/machinedetails_obj.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="json" uri="http://www.atg.com/taglibs/json" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/erroroccurred.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/erroroccurred.jsp
index 963127672d..30d92cde49 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/erroroccurred.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/erroroccurred.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/head.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/head.jsp
index 8e6e3e5e6f..cb36c70a42 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/head.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/head.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/index.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/index.jsp
index 2b1e06a114..8ab626b9f3 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/index.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/index.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/jobdetails.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/jobdetails.jsp
index d6ee1b026b..6723c71970 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/jobdetails.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/jobdetails.jsp
@@ -1,6 +1,6 @@
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listjobs.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listjobs.jsp
index aa3a1af38d..1d184f2c49 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listjobs.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listjobs.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listmachines.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listmachines.jsp
index 602e64c2d1..89f7656448 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listmachines.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/listmachines.jsp
@@ -1,5 +1,5 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
+<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/login.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/login.jsp
index 4262810fd1..d109fdfb54 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/login.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/login.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%--
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/machinedetails.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/machinedetails.jsp
index 0aa7388fbb..82a70bd09e 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/machinedetails.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/machinedetails.jsp
@@ -1,7 +1,7 @@
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
-<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
+<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<%--
Copyright (c) 2021 The University of Manchester
diff --git a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/password.jsp b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/password.jsp
index 398ea1f8da..34b4a2c0e5 100644
--- a/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/password.jsp
+++ b/SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/password.jsp
@@ -1,4 +1,4 @@
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="c" uri="jakarta.tags.core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%--
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/SupportQueries.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/SupportQueries.java
index 7713bc4a22..32c204f88f 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/SupportQueries.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/SupportQueries.java
@@ -32,42 +32,58 @@ public interface SupportQueries {
/** Insert a request-by-size. */
@Parameter("job_id")
@Parameter("num_boards")
- String TEST_INSERT_REQ_SIZE =
- "INSERT INTO job_request(job_id, num_boards) VALUES (?, ?)";
+ String TEST_INSERT_REQ_SIZE = """
+ INSERT INTO job_request(
+ job_id, num_boards)
+ VALUES (?, ?)
+ """;
/** Insert a request-by-dimensions. */
@Parameter("job_id")
@Parameter("width")
@Parameter("height")
@Parameter("max_dead_boards")
- String TEST_INSERT_REQ_DIMS =
- "INSERT INTO job_request(job_id, width, height, "
- + "max_dead_boards) VALUES (?, ?, ?, ?)";
+ String TEST_INSERT_REQ_DIMS = """
+ INSERT INTO job_request(
+ job_id, width, height, max_dead_boards)
+ VALUES (?, ?, ?, ?)
+ """;
/** Insert a request-for-a-board. */
@Parameter("job_id")
@Parameter("board_id")
- String TEST_INSERT_REQ_BOARD =
- "INSERT INTO job_request(job_id, board_id) VALUES (?, ?)";
+ String TEST_INSERT_REQ_BOARD = """
+ INSERT INTO job_request(
+ job_id, board_id)
+ VALUES (?, ?)
+ """;
/** Count the jobs. */
@ResultColumn("cnt")
@SingleRowResult
- String TEST_COUNT_JOBS = "SELECT COUNT(*) AS cnt FROM jobs";
+ String TEST_COUNT_JOBS = """
+ SELECT COUNT(*) AS cnt
+ FROM jobs
+ """;
/** Count the active allocation requests. */
@Parameter("job_state")
@ResultColumn("cnt")
@SingleRowResult
- String TEST_COUNT_REQUESTS =
- "SELECT COUNT(*) AS cnt FROM job_request "
- + "JOIN jobs USING (job_id) WHERE job_state = :job_state";
+ String TEST_COUNT_REQUESTS = """
+ SELECT COUNT(*) AS cnt
+ FROM job_request
+ JOIN jobs USING (job_id)
+ WHERE job_state = :job_state
+ """;
/** Count the active power change requests. */
@ResultColumn("cnt")
@SingleRowResult
- String TEST_COUNT_POWER_CHANGES =
- "SELECT COUNT(*) AS cnt FROM pending_changes";
+ String TEST_COUNT_POWER_CHANGES = """
+ SELECT COUNT(*) AS cnt
+ FROM pending_changes
+ """;
/** Count the active power change requests. */
@ResultColumn("cnt")
@@ -78,27 +94,39 @@ public interface SupportQueries {
/** Directly set the state of a job. */
@Parameter("state")
@Parameter("job")
- String TEST_SET_JOB_STATE =
- "UPDATE jobs SET job_state = :state WHERE job_id = :job";
+ String TEST_SET_JOB_STATE = """
+ UPDATE jobs
+ SET job_state = :state
+ WHERE job_id = :job
+ """;
/** Directly set when a job died. */
@Parameter("timestamp")
@Parameter("job")
- String TEST_SET_JOB_DEATH_TIME =
- "UPDATE jobs SET death_timestamp = :timestamp WHERE job_id = :job";
+ String TEST_SET_JOB_DEATH_TIME = """
+ UPDATE jobs
+ SET death_timestamp = :timestamp
+ WHERE job_id = :job
+ """;
/** Get the quota for a user on a machine. */
@Parameter("machine_id")
@Parameter("user_id")
@ResultColumn("quota")
- String TEST_GET_QUOTA =
- "SELECT quota FROM quotas WHERE user_id = ?";
+ String TEST_GET_QUOTA = """
+ SELECT quota
+ FROM quotas
+ WHERE user_id = ?
+ """;
/** Set the quota for a group. */
@Parameter("quota")
@Parameter("group")
- String TEST_SET_QUOTA =
- "UPDATE user_groups SET quota = :quota WHERE group_id = :group";
+ String TEST_SET_QUOTA = """
+ UPDATE user_groups
+ SET quota = :quota
+ WHERE group_id = :group
+ """;
/** Create a machine, specifying the ID. */
@Parameter("machine_id")
@@ -107,10 +135,11 @@ public interface SupportQueries {
@Parameter("height")
@Parameter("depth")
@GeneratesID
- String INSERT_MACHINE =
- "INSERT INTO machines(machine_id, machine_name, "
- + "width, height, depth, board_model) "
- + "VALUES (?, ?, ?, ?, ?, 5)";
+ String INSERT_MACHINE = """
+ INSERT INTO machines(
+ machine_id, machine_name, width, height, depth, board_model)
+ VALUES (?, ?, ?, ?, ?, 5)
+ """;
/** Create a BMP, specifying the ID. */
@Parameter("bmp_id")
@@ -119,9 +148,11 @@ public interface SupportQueries {
@Parameter("cabinet")
@Parameter("frame")
@GeneratesID
- String INSERT_BMP_WITH_ID =
- "INSERT INTO bmp(bmp_id, machine_id, address, "
- + "cabinet, frame) VALUES (?, ?, ?, ?, ?)";
+ String INSERT_BMP_WITH_ID = """
+ INSERT INTO bmp(
+ bmp_id, machine_id, address, cabinet, frame)
+ VALUES (?, ?, ?, ?, ?)
+ """;
/** Create a user, specifying the ID. */
@Parameter("user_id")
@@ -129,26 +160,33 @@ public interface SupportQueries {
@Parameter("trust_level")
@Parameter("disabled")
@GeneratesID
- String INSERT_USER = "INSERT INTO user_info(user_id, user_name, "
- + "trust_level, disabled, encrypted_password) "
- + "VALUES (?, ?, ?, ?, '*')";
+ String INSERT_USER = """
+ INSERT INTO user_info(
+ user_id, user_name, trust_level, disabled, encrypted_password)
+ VALUES (?, ?, ?, ?, '*')
+ """;
/** Create a group, specifying the ID. */
@Parameter("group_id")
@Parameter("group_name")
@Parameter("quota")
@GeneratesID
- String INSERT_GROUP = "INSERT INTO "
- + "user_groups(group_id, group_name, quota, group_type) "
- + "VALUES (?, ?, ?, 0)";
+ String INSERT_GROUP = """
+ INSERT INTO user_groups(
+ group_id, group_name, quota, group_type)
+ VALUES (?, ?, ?, 0)
+ """;
/** Create a user/group association, specifying the ID. */
@Parameter("membership_id")
@Parameter("user_id")
@Parameter("group_id")
@GeneratesID
- String INSERT_MEMBER = "INSERT group_memberships("
- + "membership_id, user_id, group_id) VALUES (?, ?, ?)";
+ String INSERT_MEMBER = """
+ INSERT INTO group_memberships(
+ membership_id, user_id, group_id)
+ VALUES (?, ?, ?)
+ """;
/** Create a board, specifying the ID. */
@Parameter("board_id")
@@ -163,11 +201,12 @@ public interface SupportQueries {
@Parameter("root_y")
@Parameter("board_power")
@GeneratesID
- String INSERT_BOARD_WITH_ID =
- "INSERT INTO boards(board_id, address, "
- + "bmp_id, board_num, machine_id, x, y, z, "
- + "root_x, root_y, board_power) "
- + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ String INSERT_BOARD_WITH_ID = """
+ INSERT INTO boards(
+ board_id, address, bmp_id, board_num, machine_id, x, y, z,
+ root_x, root_y, board_power)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """;
/** Create a job, specifying timestamps. */
@Parameter("machine_id")
@@ -182,10 +221,11 @@ public interface SupportQueries {
@Parameter("keepalive_interval")
@Parameter("keepalive_timestamp")
@GeneratesID
- String INSERT_JOB_WITH_TIMESTAMPS =
- "INSERT INTO jobs(machine_id, owner, group_id, root_id, "
- + "job_state, create_timestamp, allocation_timestamp, "
- + "death_timestamp, allocation_size, "
- + "keepalive_interval, keepalive_timestamp) "
- + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ String INSERT_JOB_WITH_TIMESTAMPS = """
+ INSERT INTO jobs(
+ machine_id, owner, group_id, root_id, job_state,
+ create_timestamp, allocation_timestamp, death_timestamp,
+ allocation_size, keepalive_interval, keepalive_timestamp)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """;
}
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/TestSupport.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/TestSupport.java
index 990d21c345..860c103180 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/TestSupport.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/TestSupport.java
@@ -35,6 +35,7 @@
import java.time.Instant;
import java.util.Collection;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.IntConsumer;
import java.util.function.ObjIntConsumer;
@@ -168,25 +169,34 @@ protected void killDB() throws IOException {
}
}
+ private static void checkKey(String name, int expected,
+ Optional got) {
+ if (got.isPresent() && got.get() != expected) {
+ log.warn("{} created with ID {} and not {}", name, got.get(),
+ expected);
+ }
+ }
+
private static void makeMachine(Connection c, int width, int height,
int depth) {
try (var u = c.update(INSERT_MACHINE)) {
- u.call(MACHINE, MACHINE_NAME, width, height, depth);
+ checkKey("Machine", MACHINE,
+ u.key(MACHINE, MACHINE_NAME, width, height, depth));
}
try (var u = c.update(INSERT_BMP_WITH_ID)) {
- u.call(BMP, MACHINE, BMP_ADDR, 1, 1);
+ checkKey("BMP", BMP, u.key(BMP, MACHINE, BMP_ADDR, 1, 1));
}
}
private static void makeUser(Connection c) {
try (var u = c.update(INSERT_USER)) {
- u.call(USER, USER_NAME, BASIC, true);
+ checkKey("User", USER, u.key(USER, USER_NAME, BASIC, true));
}
try (var u = c.update(INSERT_GROUP)) {
- u.call(GROUP, GROUP_NAME, INITIAL_QUOTA);
+ checkKey("Group", GROUP, u.key(GROUP, GROUP_NAME, INITIAL_QUOTA));
}
try (var u = c.update(INSERT_MEMBER)) {
- u.call(MEMBERSHIP, USER, GROUP);
+ checkKey("Membership", MEMBERSHIP, u.key(MEMBERSHIP, USER, GROUP));
}
}
@@ -204,8 +214,8 @@ private static void setupDB1(Connection c) {
makeMachine(c, 1, 1, 1);
// Add one board to the machine
try (var u = c.update(INSERT_BOARD_WITH_ID)) {
- assertEquals(1, u.call(BOARD, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0,
- 0, 0, false));
+ checkKey("Board", BOARD, u.key(BOARD, BOARD_ADDR, BMP, 0, MACHINE,
+ 0, 0, 0, 0, 0, false));
}
// A disabled permission-less user with a quota
makeUser(c);
@@ -226,9 +236,12 @@ private static void setupDB3(Connection c) {
// Add three connected boards to the machine
int b0 = BOARD, b1 = BOARD + 1, b2 = BOARD + 2;
try (var u = c.update(INSERT_BOARD_WITH_ID)) {
- u.call(b0, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0, 0, 0, false);
- u.call(b1, "2.2.2.3", BMP, 1, MACHINE, 0, 0, 1, 8, 4, false);
- u.call(b2, "2.2.2.4", BMP, 2, MACHINE, 0, 0, 2, 4, 8, false);
+ checkKey("Board", b0, u.key(b0, BOARD_ADDR, BMP, 0, MACHINE, 0, 0,
+ 0, 0, 0, false));
+ checkKey("Board", b1, u.key(b1, "2.2.2.3", BMP, 1, MACHINE, 0, 0, 1,
+ 8, 4, false));
+ checkKey("Board", b2, u.key(b2, "2.2.2.4", BMP, 2, MACHINE, 0, 0, 2,
+ 4, 8, false));
}
try (var u = c.update(INSERT_LINK)) {
u.call(b0, 0, b1, 3, true);
@@ -303,8 +316,11 @@ protected static int makeFinishedJob(Connection c, int size, int time) {
*/
protected static void allocateBoardToJob(Connection c, int boardId,
Integer jobId) {
- try (var u = c.update("UPDATE boards SET allocated_job = :job "
- + "WHERE board_id = :board")) {
+ try (var u = c.update("""
+ UPDATE boards
+ SET allocated_job = :job
+ WHERE board_id = :board
+ """)) {
u.call(jobId, boardId);
}
}
@@ -321,16 +337,20 @@ protected static void allocateBoardToJob(Connection c, int boardId,
*/
protected static void setAllocRoot(Connection c, int jobId,
Integer boardId) {
- try (var u = c.update("UPDATE jobs SET root_id = :board, "
- + "width = 1, height = 1, depth = 1 "
- + "WHERE job_id = :job")) {
+ try (var u = c.update("""
+ UPDATE jobs
+ SET root_id = :board, width = 1, height = 1, depth = 1
+ WHERE job_id = :job
+ """)) {
u.call(boardId, jobId);
}
}
protected List getReports() {
return db.execute(c -> {
- try (var q = c.query("SELECT reported_issue FROM board_reports")) {
+ try (var q = c.query("""
+ SELECT reported_issue FROM board_reports
+ """)) {
return q.call(string("reported_issue"));
}
});
@@ -443,7 +463,10 @@ protected void withJob(IntConsumer act) {
protected void nukeJob(int jobId) {
db.executeVoid(c -> {
- try (var u = c.update("DELETE FROM jobs WHERE job_id = ?")) {
+ try (var u = c.update("""
+ DELETE FROM jobs
+ WHERE job_id = ?
+ """)) {
u.call(jobId);
}
});
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/admin/MDefLoaderTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/admin/MDefLoaderTest.java
index 474992e1d3..52bb0a016d 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/admin/MDefLoaderTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/admin/MDefLoaderTest.java
@@ -18,6 +18,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import static uk.ac.manchester.spinnaker.alloc.db.Row.integer;
import static uk.ac.manchester.spinnaker.alloc.db.Row.string;
@@ -26,6 +27,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
@@ -49,6 +51,7 @@
@SpringBootTest
@TestInstance(PER_CLASS)
@ActiveProfiles("unittest")
+@Execution(SAME_THREAD)
class MDefLoaderTest extends SimpleDBTestBase {
@ResultColumn("c")
@SingleRowResult
@@ -72,6 +75,9 @@ class MDefLoaderTest extends SimpleDBTestBase {
@Value("classpath:bad-board-example.json")
private Resource badBoard;
+ @Value("classpath:bad-board-example2.json")
+ private Resource badBoard2;
+
@Test
void readSingleBoardExample() throws IOException {
var machines = loader.readMachineDefinitions(singleBoard.getFile());
@@ -90,7 +96,7 @@ void readSingleBoardExample() throws IOException {
}
@Test
- void readBadBoardExample() throws IOException {
+ void readBadBoardExample() {
var e = assertThrows(IOException.class,
() -> loader.readMachineDefinitions(badBoard.getFile()));
assertEquals(
@@ -99,6 +105,16 @@ void readBadBoardExample() throws IOException {
e.getMessage());
}
+ @Test
+ void readBadBoardExample2() {
+ var e = assertThrows(IOException.class,
+ () -> loader.readMachineDefinitions(badBoard2.getFile()));
+ assertEquals(
+ "failed to validate configuration: "
+ + "'1.2.3.4.5.6.not-an-ip' is a bad IPv4 address",
+ e.getMessage());
+ }
+
@Test
@SuppressWarnings("deprecation")
void loadSingleBoardExample() throws IOException {
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTest.java
index cd43412d4e..576649bda9 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTest.java
@@ -18,6 +18,7 @@
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import static uk.ac.manchester.spinnaker.alloc.model.JobState.DESTROYED;
import static uk.ac.manchester.spinnaker.alloc.model.JobState.POWER;
import static uk.ac.manchester.spinnaker.alloc.model.JobState.QUEUED;
@@ -30,6 +31,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -53,6 +55,7 @@
"spalloc.sqlite.lock-note-threshold=2200ms",
"spalloc.sqlite.lock-warn-threshold=3s"
})
+@Execution(SAME_THREAD)
class AllocatorTest extends TestSupport {
@Autowired
@@ -382,9 +385,12 @@ public void expireReady() throws Exception {
getAllocTester().destroyJob(job, "test");
c.update("DELETE FROM job_request").call();
c.update("DELETE FROM pending_changes").call();
- c.update("UPDATE boards SET allocated_job = NULL, "
- + "power_on_timestamp = 0, "
- + "power_off_timestamp = 0").call();
+ c.update("""
+ UPDATE boards
+ SET allocated_job = NULL,
+ power_on_timestamp = 0,
+ power_off_timestamp = 0
+ """).call();
});
}
}
@@ -395,7 +401,7 @@ public void tombstone() throws Exception {
doTransactionalTest(() -> {
assumeTrue(db.isHistoricalDBAvailable());
- try (Connection histConn = db.getHistoricalConnection()) {
+ try (var histConn = db.getHistoricalConnection()) {
int job = makeQueuedJob(1);
conn.update(TEST_SET_JOB_STATE).call(DESTROYED, job);
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/FirmwareLoaderTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/FirmwareLoaderTest.java
index 53c64c36c9..91d7093b9c 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/FirmwareLoaderTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/FirmwareLoaderTest.java
@@ -18,6 +18,7 @@
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
//import static uk.ac.manchester.spinnaker.alloc.allocator.Cfg.BOARD;
import static uk.ac.manchester.spinnaker.alloc.model.JobState.READY;
@@ -28,6 +29,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -49,6 +51,7 @@
@TestPropertySource(properties = {
"spalloc.transceiver.fpga-reload=true" // Enable reloading!
})
+@Execution(SAME_THREAD)
class FirmwareLoaderTest extends TestSupport {
private static final int TEST_TIMEOUT = 10;
@@ -145,8 +148,11 @@ private void resetDBState(Connection c, int job) throws Exception {
c.update("DELETE FROM job_request").call();
c.update("DELETE FROM pending_changes").call();
// Board must be bootable now to not interfere with following tests
- c.update("UPDATE boards SET allocated_job = NULL, "
- + "power_on_timestamp = 0, power_off_timestamp = 0").call();
+ c.update("""
+ UPDATE boards
+ SET allocated_job = NULL,
+ power_on_timestamp = 0, power_off_timestamp = 0
+ """).call();
});
}
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManagerTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManagerTest.java
index 1a918bc052..7caa735567 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManagerTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/QuotaManagerTest.java
@@ -17,12 +17,14 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import static uk.ac.manchester.spinnaker.alloc.db.Row.int64;
import java.io.IOException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -34,6 +36,7 @@
@SpringBootTest
@SpringJUnitWebConfig(TestSupport.Config.class)
@ActiveProfiles("unittest")
+@Execution(SAME_THREAD)
class QuotaManagerTest extends TestSupport {
/** Because the regular scheduled actions are not running. */
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocCoreTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocCoreTest.java
index 5ebd0422f8..c8461f77c5 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocCoreTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/SpallocCoreTest.java
@@ -329,7 +329,7 @@ void getJobs() {
assertEquals(Optional.of(USER_NAME), j.getOwner());
assertEquals(Optional.empty(), j.getUrl());
assertEquals(1, j.getBoards().size());
- assertEquals(BOARD_ADDR, j.getBoards().get(0).getAddress());
+ assertEquals(BOARD_ADDR, j.getBoards().get(0).address());
});
}
@@ -598,13 +598,10 @@ void reportIssue() {
assertEquals(List.of(), getReports());
var j = spalloc.getJob(p, jobId).orElseThrow();
- // Messy to build as usually only done by Jackson
- var r = new IssueReportRequest();
- var b = new ReportedBoard();
- b.machine = "test";
- b.address = BOARD_ADDR;
- r.issue = "test";
- r.boards = List.of(b);
+ // A bit messy to build as usually only done by Jackson
+ var r = new IssueReportRequest("test",
+ List.of(new ReportedBoard("test", null, null, null,
+ null, null, null, null, BOARD_ADDR)));
j.reportIssue(r, p);
assertEquals(List.of("test"), getReports());
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistCommsTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistCommsTest.java
index 391c855db5..19c1295428 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistCommsTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistCommsTest.java
@@ -18,6 +18,7 @@
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import java.io.IOException;
import java.util.Collection;
@@ -29,6 +30,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -46,6 +48,7 @@
@SpringBootTest
@SpringJUnitWebConfig(TestSupport.Config.class)
@ActiveProfiles("unittest")
+@Execution(SAME_THREAD)
class BlacklistCommsTest extends TestSupport {
/** Timeouts on individual tests, in seconds. */
@@ -114,8 +117,10 @@ private Future bmpWorker(Collection bmps, int count)
var future = exec.submit(() -> {
ready.fire();
// Time to allow main thread to submit the work we'll carry out
- Thread.sleep(TEST_DELAY);
- bmpCtrl.processRequests(TEST_DELAY, bmps);
+ for (int i = 0; i < count; i++) {
+ Thread.sleep(TEST_DELAY);
+ bmpCtrl.processRequests(TEST_DELAY, bmps);
+ }
return BMP_DONE_TOKEN;
});
ready.await();
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStoreTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStoreTest.java
index 0177cdc718..52e8732f23 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStoreTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistStoreTest.java
@@ -17,6 +17,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import static uk.ac.manchester.spinnaker.alloc.db.Row.stream;
import static uk.ac.manchester.spinnaker.machine.Direction.EAST;
import static uk.ac.manchester.spinnaker.machine.Direction.NORTH;
@@ -33,6 +34,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -48,6 +50,7 @@
@SpringBootTest
@SpringJUnitWebConfig(TestSupport.Config.class)
@ActiveProfiles("unittest")
+@Execution(SAME_THREAD)
class BlacklistStoreTest extends TestSupport {
private BlacklistStore.TestAPI testAPI;
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/MockTransceiver.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/MockTransceiver.java
index 759f8c8559..dc8d9af110 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/MockTransceiver.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/bmp/MockTransceiver.java
@@ -15,15 +15,13 @@
*/
package uk.ac.manchester.spinnaker.alloc.bmp;
-import static java.nio.ByteBuffer.allocate;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.unmodifiableMap;
import static org.apache.commons.io.IOUtils.readFully;
import static org.slf4j.LoggerFactory.getLogger;
import static uk.ac.manchester.spinnaker.messages.model.PowerCommand.POWER_ON;
-// TODO use ByteBuffer.slice(int,int) from Java 14 onwards
-import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import static uk.ac.manchester.spinnaker.utils.UnitConstants.MEGABYTE;
import java.io.IOException;
@@ -35,13 +33,12 @@
import java.util.Map;
import java.util.zip.CRC32;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-
import org.slf4j.Logger;
import com.google.errorprone.annotations.concurrent.GuardedBy;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import uk.ac.manchester.spinnaker.machine.MemoryLocation;
import uk.ac.manchester.spinnaker.machine.board.BMPBoard;
import uk.ac.manchester.spinnaker.machine.board.BMPCoords;
@@ -101,7 +98,7 @@ public static MockTransceiver getCurrentMock() {
private MockTransceiver(String machineName, BMPConnectionData data,
ValueHolder setBlacklist) {
log.info("constructed dummy transceiver for {} ({} : {})", machineName,
- data.ipAddress, data.boards);
+ data.ipAddress(), data.boards());
status = new HashMap<>();
this.setBlacklist = setBlacklist;
current = this;
@@ -121,7 +118,7 @@ public static void setBlacklist(String blacklist) {
*/
private static ByteBuffer syntheticVersionData(short versionCode) {
byte zero = 0;
- var b = allocate(VERSION_INFO_SIZE).order(LITTLE_ENDIAN);
+ var b = alloc(VERSION_INFO_SIZE);
b.put(zero);
b.put(zero);
b.put(zero);
@@ -142,7 +139,7 @@ public void power(PowerCommand powerCommand, BMPCoords bmp,
Collection boards) {
log.info("power({},{},{})", powerCommand, bmp, boards);
for (var b : boards) {
- status.put(b.board, powerCommand == POWER_ON);
+ status.put(b.board(), powerCommand == POWER_ON);
}
}
@@ -186,7 +183,7 @@ public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) {
private static final int MEM_SIZE = 8 * MEGABYTE;
private static ByteBuffer allocateMemory() {
- var buf = allocate(MEM_SIZE).order(LITTLE_ENDIAN);
+ var buf = alloc(MEM_SIZE);
buf.position(0).limit(MEM_SIZE);
return buf;
}
@@ -201,8 +198,8 @@ public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board,
log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress,
length);
// Pad to length
- var b = slice(flash, baseAddress.address, length);
- if (baseAddress.address == SERIAL_FLASH_BLACKLIST_OFFSET) {
+ var b = flash.slice(baseAddress.address(), length).order(LITTLE_ENDIAN);
+ if (baseAddress.address() == SERIAL_FLASH_BLACKLIST_OFFSET) {
b.put(new Blacklist(blacklistData).getRawData());
b.position(0);
}
@@ -213,7 +210,7 @@ public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board,
public ByteBuffer readBMPMemory(BMPCoords bmp, BMPBoard board,
MemoryLocation baseAddress, int length) {
log.info("readBMPMemory({},{},{},{})", bmp, board, baseAddress, length);
- return slice(memory, baseAddress.address, length);
+ return memory.slice(baseAddress.address(), length).order(LITTLE_ENDIAN);
}
@Override
@@ -227,7 +224,7 @@ public void writeBMPMemory(BMPCoords bmp, BMPBoard board,
MemoryLocation baseAddress, ByteBuffer data) {
log.info("writeBMPMemory({},{},{}:{})", bmp, board, baseAddress,
data.remaining());
- slice(memory, baseAddress.address, data.remaining())
+ memory.slice(baseAddress.address(), data.remaining())
.put(data.duplicate());
}
@@ -236,7 +233,7 @@ public void writeFlash(@Valid BMPCoords bmp, @Valid BMPBoard board,
@NotNull MemoryLocation baseAddress, @NotNull ByteBuffer data) {
log.info("writeFlash({},{},{},{})", bmp, board, baseAddress,
data.remaining());
- slice(memory, baseAddress.address, data.remaining())
+ memory.slice(baseAddress.address(), data.remaining())
.put(data.duplicate());
var blData = data.duplicate().position(BMP_FLASH_BLACKLIST_OFFSET);
synchronized (setBlacklist) {
@@ -253,7 +250,8 @@ public void writeSerialFlash(BMPCoords bmp, BMPBoard board,
MemoryLocation baseAddress, ByteBuffer data) {
log.info("writeSerialFlash({},{},{}:{})", bmp, board, baseAddress,
data.remaining());
- var b = slice(flash, baseAddress.address, data.remaining()).put(data);
+ var b = flash.slice(baseAddress.address(), data.remaining())
+ .order(LITTLE_ENDIAN).put(data);
b.position(SERIAL_FLASH_BLACKLIST_OFFSET);
var bl = new Blacklist(b);
synchronized (setBlacklist) {
@@ -271,7 +269,7 @@ public void writeSerialFlash(BMPCoords bmp, BMPBoard board,
throws IOException {
log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress,
size);
- slice(flash, baseAddress.address, size).put(readFully(stream, size));
+ flash.slice(baseAddress.address(), size).put(readFully(stream, size));
}
@Override
@@ -288,7 +286,7 @@ public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board,
log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress,
length);
var crc = new CRC32();
- crc.update(slice(flash, baseAddress.address, length));
+ crc.update(flash.slice(baseAddress.address(), length));
return (int) (crc.getValue() & CRC_MASK);
}
}
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/JsonTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/JsonTest.java
index 2b125c3867..1f202b3bbe 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/JsonTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/JsonTest.java
@@ -30,6 +30,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
import uk.ac.manchester.spinnaker.spalloc.messages.BoardCoordinates;
@@ -48,6 +50,8 @@ class JsonTest {
JsonTest() {
// Set up the mapper in the same way that ServiceConfig does
mapper = JsonMapper.builder().findAndAddModules()
+ .addModule(new JavaTimeModule())
+ .addModule(new Jdk8Module())
.disable(WRITE_DATES_AS_TIMESTAMPS)
.propertyNamingStrategy(SNAKE_CASE).build();
}
@@ -76,13 +80,19 @@ void testJobMachineInfo() throws IOException, JSONException {
List.of(new Connection(ZERO_ZERO, "2.3.4.5")),
"gorp", List.of(new BoardCoordinates(0, 1, 2)));
- JSONAssert.assertEquals(
- "{ 'boards': [[0,1,2]], "
- + "'connections': [[[0,0],'2.3.4.5']], "
- + "'width': 0, "
- + "'height': 0, "
- + "'machine_name': 'gorp' }",
- serialize(r), true);
+ JSONAssert.assertEquals("""
+ {
+ 'boards': [
+ [0,1,2]
+ ],
+ 'connections': [
+ [[0, 0], '2.3.4.5']
+ ],
+ 'width': 0,
+ 'height': 0,
+ 'machine_name': 'gorp'
+ }
+ """, serialize(r), true);
}
@Test
@@ -95,14 +105,16 @@ void testJobState() throws IOException, JSONException {
r.setKeepalive(321);
r.setKeepalivehost("127.0.0.1");
- JSONAssert.assertEquals(
- "{ 'state': 2, "
- + "'start_time': 123, "
- + "'power': false, "
- + "'reason': 'gorp', "
- + "'keepalive': 321, "
- + "'keepalivehost': '127.0.0.1' }",
- serialize(r.build()), true);
+ JSONAssert.assertEquals("""
+ {
+ 'state': 2,
+ 'start_time': 123,
+ 'power': false,
+ 'reason': 'gorp',
+ 'keepalive': 321,
+ 'keepalivehost': '127.0.0.1'
+ }
+ """, serialize(r.build()), true);
}
@Test
@@ -119,21 +131,24 @@ void testJobDescription() throws IOException, JSONException {
r.setStartTime(321.);
r.setState(State.POWER);
- JSONAssert.assertEquals(
- "[{ 'allocated_machine_name': 'foo', "
- + "'args': [0], "
- + "'boards': [], "
- + "'job_id': 1, "
- + "'keepalive': 123, "
- + "'keepalivehost': '127.0.0.1', "
- + "'kwargs': {}, "
- + "'owner': 'bar', "
- + "'power': false, "
- + "'reason': null, "
- + "'state': 2, "
- + "'start_time': 321 "
- + "}]",
- serialize(new JobDescription[] {r.build()}), true);
+ JSONAssert.assertEquals("""
+ [
+ {
+ 'allocated_machine_name': 'foo',
+ 'args': [0],
+ 'boards': [],
+ 'job_id': 1,
+ 'keepalive': 123,
+ 'keepalivehost': '127.0.0.1',
+ 'kwargs': {},
+ 'owner': 'bar',
+ 'power': false,
+ 'reason': null,
+ 'state': 2,
+ 'start_time': 321
+ }
+ ]
+ """, serialize(new JobDescription[] {r.build()}), true);
}
@Test
@@ -141,11 +156,18 @@ void testMachine() throws IOException, JSONException {
var r = new Machine("gorp", List.of("foo", "bar"), 0, 0, null,
null);
- JSONAssert.assertEquals(
- "[{ 'name': 'gorp', 'tags': ['foo', 'bar'], "
- + "'dead_boards': [], 'dead_links': [], "
- + "'height': 0, 'width': 0 }]",
- serialize(new Machine[] {r}), true);
+ JSONAssert.assertEquals("""
+ [
+ {
+ 'name': 'gorp',
+ 'tags': ['foo', 'bar'],
+ 'dead_boards': [],
+ 'dead_links': [],
+ 'height': 0,
+ 'width': 0
+ }
+ ]
+ """, serialize(new Machine[] {r}), true);
}
@Test
@@ -155,12 +177,17 @@ void testWhereIs() throws IOException, JSONException {
"gorp", new ChipLocation(0, 0),
new BoardPhysicalCoordinates(0, 1, 2));
- JSONAssert.assertEquals(
- "{'chip': [0,0], 'board_chip': [0,0],"
- + "'job_chip': [0,0], 'job_id': 0,"
- + "'logical': [0,1,2], 'physical': [0,1,2],"
- + "'machine': 'gorp'}",
- serialize(r), true);
+ JSONAssert.assertEquals("""
+ {
+ 'chip': [0, 0],
+ 'board_chip': [0, 0],
+ 'job_chip': [0, 0],
+ 'job_id': 0,
+ 'logical': [0, 1, 2],
+ 'physical': [0, 1, 2],
+ 'machine': 'gorp'
+ }
+ """, serialize(r), true);
}
}
}
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTest.java
index 6d0d3ae39c..22a6c3f909 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/V1CompatTest.java
@@ -18,6 +18,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import static java.lang.String.format;
import static java.time.temporal.ChronoUnit.MILLIS;
import static java.util.regex.Pattern.compile;
@@ -43,6 +44,8 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.Timeout;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -61,7 +64,10 @@
"spalloc.compat.service-user=" + TestSupport.USER_NAME,
"spalloc.compat.service-group=" + TestSupport.GROUP_NAME
})
+@Execution(SAME_THREAD)
class V1CompatTest extends TestSupport {
+ // Take care in this class: JSON documents must be SINGLE LINE too
+
/** The name of the database file. */
static final String DB = "target/compat_test.sqlite3";
@@ -72,6 +78,7 @@ class V1CompatTest extends TestSupport {
@BeforeEach
@SuppressWarnings("deprecation")
+ @Timeout(1)
void checkSetup(@Autowired V1CompatService compat) throws IOException {
assumeTrue(db != null, "spring-configured DB engine absent");
killDB();
@@ -157,22 +164,38 @@ private static String create(PrintWriter to, UncheckedLineReader from,
private static void destroy(PrintWriter to, UncheckedLineReader from,
Object jobId) {
+ destroy(to, from, jobId, VOID_RESPONSE);
+ }
+
+ private static void destroy(PrintWriter to, UncheckedLineReader from,
+ Object jobId, String expecting) {
to.println("{\"command\":\"destroy_job\",\"args\":[" + jobId
+ "],\"kwargs\":{\"reason\":\"whatever\"}}");
- assertEquals(VOID_RESPONSE, from.readLine());
+ assertEquals(expecting, from.readLine());
}
// The actual tests
+ /** Big enough to stress test some internal pools. */
+ private static final int MACHINERY_TEST_SIZE = 50;
+
+ private static final int MACHINERY_TEST_TIMEOUT = 15;
+
@Test
- public void testMachineryTest() throws Exception {
- for (int i = 0; i < 100; i++) {
+ @Timeout(MACHINERY_TEST_TIMEOUT)
+ public void testMachineryTestBidirectional() throws Exception {
+ for (int i = 0; i < MACHINERY_TEST_SIZE; i++) {
withInstance((to, from) -> {
to.println();
from.readLine();
});
}
- for (int i = 0; i < 100; i++) {
+ }
+
+ @Test
+ @Timeout(MACHINERY_TEST_TIMEOUT)
+ public void testMachineryTestUnidirectional() throws Exception {
+ for (int i = 0; i < MACHINERY_TEST_SIZE; i++) {
withInstance((to, from) -> {
to.println();
});
@@ -183,6 +206,7 @@ public void testMachineryTest() throws Exception {
@Nested
class WithoutJob {
@Test
+ @Timeout(5)
void version() throws Exception {
var response = "{\"return\":\"" + VERSION + "\"}";
withInstance((to, from) -> {
@@ -192,6 +216,7 @@ void version() throws Exception {
}
@Test
+ @Timeout(5)
void listMachines() throws Exception {
var machinesResponse = "{\"return\":[{\"name\":\"" + MACHINE_NAME
+ "\",\"tags\":[],\"width\":1,\"height\":1,"
@@ -211,6 +236,7 @@ void listMachines() throws Exception {
}
@Test
+ @Timeout(5)
void listJobs() throws Exception {
var jobsResponse = "{\"return\":[]}";
withInstance((to, from) -> {
@@ -220,6 +246,7 @@ void listJobs() throws Exception {
}
@Test
+ @Timeout(5)
void notifyJob() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\": \"notify_job\"}");
@@ -230,6 +257,7 @@ void notifyJob() throws Exception {
}
@Test
+ @Timeout(5)
void notifyMachine() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\": \"notify_machine\"}");
@@ -246,6 +274,7 @@ void notifyMachine() throws Exception {
}
@Test
+ @Timeout(5)
void whereIs() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\": \"where_is\", \"kwargs\":{"
@@ -264,6 +293,7 @@ void whereIs() throws Exception {
}
@Test
+ @Timeout(5)
void getBoardAtPosition() throws Exception {
// Physical->Logical map
var response = "{\"return\":[0,0,0]}";
@@ -277,6 +307,7 @@ void getBoardAtPosition() throws Exception {
}
@Test
+ @Timeout(5)
void getBoardPosition() throws Exception {
// Logical->Physical map
var response = "{\"return\":[1,1,0]}";
@@ -289,20 +320,53 @@ void getBoardPosition() throws Exception {
}
@Test
- void jobCreateDelete() throws Exception {
+ @Timeout(5)
+ void jobCreateDeleteZeroArgs() throws Exception {
withInstance((to, from) -> {
var jobId = create(to, from);
+ log.debug("created() with ID={}", jobId);
destroy(to, from, jobId);
+ log.debug("destroyed() ID={}", jobId);
+ });
+ }
- jobId = create(to, from, 1);
+ @Test
+ @Timeout(5)
+ void jobCreateDeleteOneArg() throws Exception {
+ withInstance((to, from) -> {
+ var jobId = create(to, from, 1);
+ log.debug("created(1) with ID={}", jobId);
destroy(to, from, jobId);
+ log.debug("destroyed(1) ID={}", jobId);
+ });
+ }
- jobId = create(to, from, 1, 1);
+ @Test
+ @Timeout(5)
+ void jobCreateDeleteTwoArgs() throws Exception {
+ withInstance((to, from) -> {
+ var jobId = create(to, from, 1, 1);
+ log.debug("created(1,1) with ID={}", jobId);
destroy(to, from, jobId);
+ log.debug("destroyed(1,1) ID={}", jobId);
+ });
+ }
- jobId = create(to, from, 0, 0, 0);
+ @Test
+ @Timeout(5)
+ void jobCreateDeleteThreeArgs() throws Exception {
+ withInstance((to, from) -> {
+ var jobId = create(to, from, 0, 0, 0);
+ log.debug("created(0,0,0) with ID={}", jobId);
destroy(to, from, jobId);
+ log.debug("destroyed(0,0,0) ID={}", jobId);
+ });
+ }
+ @Test
+ @Timeout(5)
+ void jobCreateDeleteFourArgs() throws Exception {
+ withInstance((to, from) -> {
to.println("{\"command\":\"create_job\",\"args\":[0,0,0,0],"
+ "\"kwargs\":{\"owner\":\"gorp\"," + "\"machine\":\""
+ MACHINE_NAME + "\"}}");
@@ -310,10 +374,12 @@ void jobCreateDelete() throws Exception {
"{\"exception\":"
+ "\"unsupported number of arguments: 4\"}",
from.readLine());
+ destroy(to, from, 999999999, "{\"exception\":\"no such job\"}");
});
}
@Test
+ @Timeout(5)
void compound() throws Exception {
withInstance((to, from) -> {
var jobId = create(to, from, 1, 1);
@@ -345,6 +411,7 @@ class WithJob {
// Make an allocated job for us to work with
@BeforeEach
+ @Timeout(5)
void setupJob() {
jobId = makeJob();
expectedNotification = "{\"jobs_changed\":[" + jobId + "]}";
@@ -356,6 +423,7 @@ void setupJob() {
// Get rid of the allocated job
@AfterEach
+ @Timeout(5)
void teardownJob() {
db.executeVoid(c -> {
allocateBoardToJob(c, BOARD, null);
@@ -374,6 +442,7 @@ private String readReply(UncheckedLineReader from) {
}
@Test
+ @Timeout(5)
void getJobState() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"get_job_state\",\"args\":[" + jobId
@@ -386,6 +455,7 @@ void getJobState() throws Exception {
}
@Test
+ @Timeout(5)
void getJobMachineInfo() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"get_job_machine_info\",\"args\":["
@@ -397,6 +467,7 @@ void getJobMachineInfo() throws Exception {
}
@Test
+ @Timeout(5)
void jobKeepalive() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"job_keepalive\",\"args\":[" + jobId
@@ -406,6 +477,7 @@ void jobKeepalive() throws Exception {
}
@Test
+ @Timeout(5)
void jobNotify() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"notify_job\",\"args\":[" + jobId
@@ -418,6 +490,7 @@ void jobNotify() throws Exception {
}
@Test
+ @Timeout(5)
void jobPower() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"power_off_job_boards\","
@@ -427,6 +500,7 @@ void jobPower() throws Exception {
}
@Test
+ @Timeout(5)
void whereIs() throws Exception {
withInstance((to, from) -> {
to.println("{\"command\":\"where_is\",\"kwargs\":{\"job_id\":"
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DMLTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DMLTest.java
index c2977a5168..26ad8709c2 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DMLTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DMLTest.java
@@ -271,7 +271,7 @@ void killJobAllocTask() {
@Test
void issueChangeForJob() {
assumeWritable(c);
- try (var u = c.update(issueChangeForJob)) {
+ try (var u = c.update(ISSUE_CHANGE_FOR_JOB)) {
c.transaction(() -> {
assertEquals(
List.of("job_id", "board_id", "from_state", "to_state",
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DQLTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DQLTest.java
index 2e97948df2..a9b8f48cd5 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DQLTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DQLTest.java
@@ -254,8 +254,8 @@ void getJobChipDimensions() {
var dims = q.call1(r -> new MachineDimensions(r.getInt("width"),
r.getInt("height")), NO_JOB).orElseThrow();
// These two are actually NULL when there's no job
- assertEquals(0, dims.width);
- assertEquals(0, dims.height);
+ assertEquals(0, dims.width());
+ assertEquals(0, dims.height());
});
}
}
@@ -412,7 +412,7 @@ void getAllBoardsOfAllMachines() {
@Test
void getDeadLinks() {
- try (var q = c.query(getDeadLinks)) {
+ try (var q = c.query(GET_DEAD_LINKS)) {
c.transaction(() -> {
assertEquals(List.of("machine_id"), q.getParameters());
assertEquals(List.of("board_1_x", "board_1_y", "board_1_z",
@@ -486,7 +486,7 @@ void getRootCoords() {
@Test
void getAllocationTasks() {
- try (var q = c.query(getAllocationTasks)) {
+ try (var q = c.query(GET_ALLOCATION_TASKS)) {
c.transaction(() -> {
assertEquals(List.of("job_state"), q.getParameters());
assertEquals(List.of("req_id", "job_id", "num_boards", "width",
@@ -590,7 +590,7 @@ void findRectangleAt() {
@Test
void findLocation() {
- try (var q = c.query(findLocation)) {
+ try (var q = c.query(FIND_LOCATION)) {
c.transaction(() -> {
assertEquals(List.of("machine_id", "board_id"),
q.getParameters());
@@ -1093,7 +1093,7 @@ void getLocalUserDetails() {
@Test
void getReportedBoards() {
- try (var q = c.query(getReportedBoards)) {
+ try (var q = c.query(GET_REPORTED_BOARDS)) {
c.transaction(() -> {
assertEquals(List.of("threshold"), q.getParameters());
assertEquals(List.of("board_id", "num_reports", "x", "y", "z",
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DbBasicTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DbBasicTest.java
index e46a0787ca..ded0c14684 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DbBasicTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/DbBasicTest.java
@@ -32,8 +32,6 @@
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.test.context.ActiveProfiles;
-import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection;
-
/**
* Test that the database engine interface works and that the queries are
* synchronised with the schema. Deliberately does not do meaningful testing of
@@ -133,14 +131,15 @@ void testBadUpdates() {
}
@Test
- @SuppressWarnings("deprecation")
void testDbChanges() {
assumeWritable(c);
c.transaction(() -> {
int rows;
- ((Connection) c).update(
- "CREATE TEMPORARY TABLE foo "
- + "(k INT PRIMARY KEY AUTO_INCREMENT, x INT)").call();
+ c.update("""
+ CREATE TEMPORARY TABLE foo (
+ k INT PRIMARY KEY AUTO_INCREMENT,
+ x INT)
+ """).call();
try (var u = c.update("INSERT INTO foo(x) VALUES(?)");
var q = c.query("SELECT x FROM foo WHERE ? = ?");
var q2 = c.query("SELECT x FROM foo")) {
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthTest.java
index aab3e7288f..a52a3f47c7 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthTest.java
@@ -18,11 +18,13 @@
import static java.time.Instant.now;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
import java.io.IOException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@@ -35,6 +37,7 @@
@SpringBootTest
@SpringJUnitWebConfig(TestSupport.Config.class)
@ActiveProfiles("unittest")
+@Execution(SAME_THREAD)
class LocalAuthTest extends TestSupport {
private TestAPI authEngine;
@@ -56,10 +59,12 @@ public void unlockUser() throws Exception {
try (var c = db.getConnection()) {
c.transaction(() -> {
// 90k seconds is more than one day
- try (var setLocked =
- c.update("UPDATE user_info SET locked = :locked, "
- + "last_fail_timestamp = :time - 90000 "
- + "WHERE user_id = :user_id")) {
+ try (var setLocked = c.update("""
+ UPDATE user_info
+ SET locked = :locked,
+ last_fail_timestamp = :time - 90000
+ WHERE user_id = :user_id
+ """)) {
setLocked.call(true, now(), USER);
}
});
@@ -69,8 +74,11 @@ public void unlockUser() throws Exception {
try (var c = db.getConnection()) {
assertEquals(false, c.transaction(() -> {
- try (var q = c.query("SELECT locked FROM user_info "
- + "WHERE user_id = :user_id")) {
+ try (var q = c.query("""
+ SELECT locked
+ FROM user_info
+ WHERE user_id = :user_id
+ """)) {
return q.call1(Row.bool("locked"), USER).orElseThrow();
}
}));
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/JsonTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/JsonTest.java
index 0dfe7a82cd..18198b807d 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/JsonTest.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/JsonTest.java
@@ -17,9 +17,7 @@
import static com.fasterxml.jackson.databind.PropertyNamingStrategies.KEBAB_CASE;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.*;
import static uk.ac.manchester.spinnaker.alloc.model.PowerState.ON;
import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO;
@@ -31,9 +29,6 @@
import java.util.Optional;
import java.util.Set;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
import org.apache.cxf.jaxrs.impl.UriBuilderImpl;
import org.json.JSONException;
import org.junit.jupiter.api.Nested;
@@ -42,7 +37,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.core.UriInfo;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.BoardLocation;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Job;
import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Machine;
@@ -62,6 +61,8 @@ class JsonTest {
JsonTest() {
// Set up the mapper in the same way that ServiceConfig does
mapper = JsonMapper.builder().findAndAddModules()
+ .addModule(new JavaTimeModule())
+ .addModule(new Jdk8Module())
.disable(WRITE_DATES_AS_TIMESTAMPS)
.propertyNamingStrategy(KEBAB_CASE).build();
}
@@ -234,11 +235,16 @@ class Serialization {
@Test
void testServiceDescription() throws IOException, JSONException {
var d = new ServiceDescription();
- d.setVersion(new Version("1.2.3"));
- JSONAssert.assertEquals(
- "{ \"version\": { \"major-version\": 1,"
- + "\"minor-version\": 2, \"revision\": 3 } }",
- serialize(d), false);
+ d.setVersion(Version.parse("1.2.3"));
+ JSONAssert.assertEquals("""
+ {
+ "version": {
+ "major-version": 1,
+ "minor-version": 2,
+ "revision": 3
+ }
+ }
+ """, serialize(d), false);
}
@Test
@@ -248,23 +254,33 @@ void testStateResponse() throws IOException, JSONException {
r.setStartTime(Instant.ofEpochSecond(1633954394));
r.setKeepaliveHost("127.0.0.1");
r.setOwner("gorp");
- JSONAssert.assertEquals(
- "{ \"state\": \"READY\", "
- + "\"start-time\": \"2021-10-11T12:13:14Z\", "
- + "\"owner\": \"gorp\", "
- + "\"keepalive-host\": \"127.0.0.1\" }",
- serialize(r), false);
+ JSONAssert.assertEquals("""
+ {
+ "state": "READY",
+ "start-time": "2021-10-11T12:13:14Z",
+ "owner": "gorp",
+ "keepalive-host": "127.0.0.1"
+ }
+ """, serialize(r), false);
}
@Test
void testSubMachineResponse() throws IOException, JSONException {
var r = new SubMachineResponse(new SM(), null);
- JSONAssert.assertEquals(
- "{ \"depth\": 1, \"width\": 1, \"height\": 1,"
- + "\"machine-name\": \"gorp\","
- + "\"boards\": [[0, 0, 0]],"
- + "\"connections\": [[[0, 0], \"2.3.4.5\"]] }",
- serialize(r), true);
+ JSONAssert.assertEquals("""
+ {
+ "depth": 1,
+ "width": 1,
+ "height": 1,
+ "machine-name": "gorp",
+ "boards": [
+ [0, 0, 0]
+ ],
+ "connections": [
+ [[0, 0], "2.3.4.5"]
+ ]
+ }
+ """, serialize(r), true);
}
@Test
@@ -317,13 +333,17 @@ public Optional getRootChip() {
}
};
var r = new WhereIsResponse(loc, stubBuilder("http://localhost/"));
- JSONAssert.assertEquals(
- "{ \"machine\": \"gorp\", \"chip\": [1, 2], "
- + "\"job-id\": 12345, \"board-chip\": [3, 4],"
- + "\"job-chip\": [11, 12],"
- + "\"logical-board-coordinates\": [5, 6, 0],"
- + "\"physical-board-coordinates\": [7, 8, 9] }",
- serialize(r), false);
+ JSONAssert.assertEquals("""
+ {
+ "machine": "gorp",
+ "chip": [1, 2],
+ "job-id": 12345,
+ "board-chip": [3, 4],
+ "job-chip": [11, 12],
+ "logical-board-coordinates": [5, 6, 0],
+ "physical-board-coordinates": [7, 8, 9]
+ }
+ """, serialize(r), false);
}
}
@@ -331,41 +351,76 @@ public Optional getRootChip() {
class Deserialization {
@Test
void testCreateJobRequestSimple() throws IOException {
- var obj = "{\"owner\":\"bob\", \"keepalive-interval\":\"PT30S\"}";
- var cjr = deserialize(obj, CreateJobRequest.class);
+ var cjr = deserialize("""
+ {
+ "owner": "bob",
+ "keepalive-interval": "PT30S"
+ }
+ """, CreateJobRequest.class);
assertNotNull(cjr);
- assertEquals("bob", cjr.owner);
- assertNotNull(cjr.keepaliveInterval);
- assertEquals(30, cjr.keepaliveInterval.getSeconds());
- assertNull(cjr.dimensions);
+ assertEquals("bob", cjr.owner());
+ assertNotNull(cjr.keepaliveInterval());
+ assertEquals(30, cjr.keepaliveInterval().getSeconds());
+ assertNull(cjr.dimensions());
}
@Test
void testCreateJobRequestComplex() throws IOException {
- var obj = "{\"owner\": \"bob\", \"keepalive-interval\": \"PT30S\", "
- + "\"dimensions\": {\"width\": 1, \"height\": 2}, "
- + "\"tags\": [\"a\", \"b\"], "
- + "\"max-dead-boards\": 77, "
- + "\"machine-name\": \"gorp\"}";
- var cjr = deserialize(obj, CreateJobRequest.class);
+ var cjr = deserialize("""
+ {
+ "owner": "bob",
+ "keepalive-interval": "PT30S",
+ "dimensions": {
+ "width": 1,
+ "height": 2
+ },
+ "tags": ["a", "b"],
+ "max-dead-boards": 77,
+ "machine-name": "gorp"
+ }
+ """, CreateJobRequest.class);
assertNotNull(cjr);
- assertEquals("bob", cjr.owner);
- assertNotNull(cjr.keepaliveInterval);
- assertEquals(30, cjr.keepaliveInterval.getSeconds());
- assertNotNull(cjr.dimensions);
- assertEquals(1, cjr.dimensions.width);
- assertNotNull(cjr.tags);
- assertEquals(2, cjr.tags.size());
- assertEquals("a", cjr.tags.get(0));
- assertEquals("gorp", cjr.machineName);
- assertEquals(77, cjr.maxDeadBoards);
+ assertEquals("bob", cjr.owner());
+ assertNotNull(cjr.keepaliveInterval());
+ assertEquals(30, cjr.keepaliveInterval().getSeconds());
+ assertNotNull(cjr.dimensions());
+ assertEquals(1, cjr.dimensions().width());
+ assertEquals(List.of("a", "b"), cjr.tags());
+ assertEquals("gorp", cjr.machineName());
+ assertEquals(77, cjr.maxDeadBoards());
+ }
+
+ @Test
+ void testCreateJobRequestSpecific() throws IOException {
+ // The part that testCreateJobRequestComplex() doesn't look at
+ assertEquals(3, deserialize("""
+ {
+ "owner": "bob",
+ "keepalive-interval": "PT30S",
+ "dimensions": {
+ "width": 1,
+ "height": 2
+ },
+ "board": {
+ "cabinet": 3,
+ "frame": 4,
+ "board": 5
+ },
+ "tags": ["a", "b"],
+ "max-dead-boards": 77,
+ "machine-name": "gorp"
+ }
+ """, CreateJobRequest.class).board().cabinet());
}
@Test
void testPowerRequest() throws IOException {
- var obj = "{\"power\": \"ON\"}";
- var mp = deserialize(obj, MachinePower.class);
- assertEquals(ON, mp.getPower());
+ var mp = deserialize("""
+ {
+ "power": "ON"
+ }
+ """, MachinePower.class);
+ assertEquals(ON, mp.power());
}
}
}
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubJob.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubJob.java
index 5fc52b4dfa..8b8e460896 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubJob.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubJob.java
@@ -141,11 +141,7 @@ public void forgetProxy(ProxyCore proxy) {
@Override
public final boolean equals(Object other) {
- if (other instanceof Job) {
- var j = (Job) other;
- return getId() == j.getId();
- }
- return false;
+ return (other instanceof Job j) && (getId() == j.getId());
}
@Override
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubMachine.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubMachine.java
index cd63581c88..4512c11366 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubMachine.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubMachine.java
@@ -129,11 +129,7 @@ public List getBoardNumbers(BMPCoords bmp) {
@Override
public final boolean equals(Object other) {
- if (other instanceof Machine) {
- var m = (Machine) other;
- return getId() == m.getId();
- }
- return false;
+ return (other instanceof Machine m) && (getId() == m.getId());
}
@Override
diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubUriInfo.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubUriInfo.java
index 219a2b5e21..ed51d248ce 100644
--- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubUriInfo.java
+++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/StubUriInfo.java
@@ -18,10 +18,10 @@
import java.net.URI;
import java.util.List;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.PathSegment;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.PathSegment;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.core.UriInfo;
abstract class StubUriInfo implements UriInfo {
@Override
diff --git a/SpiNNaker-allocserv/src/test/resources/bad-board-example2.json b/SpiNNaker-allocserv/src/test/resources/bad-board-example2.json
new file mode 100644
index 0000000000..9029aefbc8
--- /dev/null
+++ b/SpiNNaker-allocserv/src/test/resources/bad-board-example2.json
@@ -0,0 +1,36 @@
+{
+ "machines" : [ {
+ "name" : "my-board",
+ "tags" : [ "single" ],
+ "width" : 1,
+ "height" : 1,
+ "dead-boards" : [ {
+ "x" : 0,
+ "y" : 0,
+ "z" : 1
+ }, {
+ "x" : 0,
+ "y" : 0,
+ "z" : 2
+ } ],
+ "dead-links" : {},
+ "board-locations" : {
+ "[x:0,y:0,z:0]" : {
+ "c" : 0,
+ "f" : 0,
+ "b" : 0
+ }
+ },
+ "bmp-ips" : {
+ "[c:0,f:0]" : "1.2.3.4.5.6.not-an-ip"
+ },
+ "spinnaker-ips" : {
+ "[x:0,y:0,z:0]" : "192.168.0.3"
+ }
+ } ],
+ "port" : 22244,
+ "ip" : "192.168.0.2",
+ "timeout-check-interval" : 5.0,
+ "max-retired-jobs" : 1200,
+ "seconds-before-free" : 30
+}
diff --git a/SpiNNaker-comms/pom.xml b/SpiNNaker-comms/pom.xml
index 24f18e65dc..8034c4fb57 100644
--- a/SpiNNaker-comms/pom.xml
+++ b/SpiNNaker-comms/pom.xml
@@ -53,7 +53,7 @@ limitations under the License.
com.fasterxml.jackson.module
- jackson-module-jaxb-annotations
+ jackson-module-jakarta-xmlbind-annotations
org.apache.commons
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/AllocatedMachine.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/AllocatedMachine.java
index e27e80ec70..6d9feda1b5 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/AllocatedMachine.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/AllocatedMachine.java
@@ -21,9 +21,6 @@
import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -33,6 +30,8 @@
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.google.errorprone.annotations.Immutable;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
import uk.ac.manchester.spinnaker.alloc.client.SpallocClient.Machine;
import uk.ac.manchester.spinnaker.machine.ChipLocation;
import uk.ac.manchester.spinnaker.machine.board.ValidTriadDepth;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BoardCoords.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BoardCoords.java
index 6b6209c494..170aee762c 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BoardCoords.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BoardCoords.java
@@ -17,11 +17,12 @@
import static java.lang.String.format;
-import java.util.Objects;
-
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.errorprone.annotations.Immutable;
+import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords;
+import uk.ac.manchester.spinnaker.machine.board.TriadCoords;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidCabinetNumber;
import uk.ac.manchester.spinnaker.machine.board.ValidFrameNumber;
@@ -30,154 +31,65 @@
import uk.ac.manchester.spinnaker.machine.board.ValidTriadZ;
import uk.ac.manchester.spinnaker.utils.validation.IPAddress;
-/** Generalised coordinates of a board. */
+/**
+ * Generalised coordinates of a board.
+ *
+ * @param x
+ * Logical triad X coordinate. Range: 0–255.
+ * @param y
+ * Logical triad Y coordinate. Range: 0–255.
+ * @param z
+ * Logical triad Z coordinate. Range: 0–2.
+ * @param cabinet
+ * Number of the cabinet containing the frame containing the board.
+ * Range: 0–31.
+ * @param frame
+ * Number of the frame (within the cabinet) containing the board.
+ * Range: 0–31.
+ * @param board
+ * Number of the board within its frame. Range: 0–23. May be
+ * {@code null} under some circumstances.
+ * @param address
+ * IP address of ethernet chip on board. May be {@code null} if the
+ * current user doesn't have permission to see the board address at
+ * this point (because it isn't allocated or booted).
+ */
@Immutable
-public class BoardCoords {
- /** Logical triad X coordinate. */
- @ValidTriadX
- private final int x;
-
- /** Logical triad Y coordinate. */
- @ValidTriadY
- private final int y;
-
- /** Logical triad Z coordinate. */
- @ValidTriadZ
- private final int z;
-
- /** Physical cabinet number. */
- @ValidCabinetNumber
- private final int cabinet;
-
- /** Physical frame number. */
- @ValidFrameNumber
- private final int frame;
-
- /** Physical board number. */
- @ValidBoardNumber
- private final Integer board;
-
- /**
- * IP address of ethernet chip. May be {@code null} if the current user
- * doesn't have permission to see the board address at this point.
- */
- @IPAddress(nullOK = true)
- private final String address;
-
+public record BoardCoords(//
+ @JsonProperty("x") @ValidTriadX int x,
+ @JsonProperty("y") @ValidTriadY int y,
+ @JsonProperty("z") @ValidTriadZ int z,
+ @JsonProperty("cabinet") @ValidCabinetNumber int cabinet,
+ @JsonProperty("frame") @ValidFrameNumber int frame,
+ @JsonProperty("board") @ValidBoardNumber Integer board,
+ @JsonProperty("address") @IPAddress(nullOK = true) String address) {
/**
- * @param x
- * Logical triad X coordinate
- * @param y
- * Logical triad Y coordinate
- * @param z
- * Logical triad Z coordinate
- * @param cabinet
- * Physical cabinet number
- * @param frame
- * Physical frame number
- * @param board
- * Physical board number
- * @param address
- * IP address of ethernet chip
- */
- BoardCoords(@JsonProperty("x") int x, @JsonProperty("y") int y,
- @JsonProperty("z") int z, @JsonProperty("cabinet") int cabinet,
- @JsonProperty("frame") int frame,
- @JsonProperty("board") Integer board,
- @JsonProperty("address") String address) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.cabinet = cabinet;
- this.frame = frame;
- this.board = board;
- this.address = address;
- }
-
- /**
- * Get the triad X coordinate. Range: 0-255.
- *
- * @return Logical triad X coordinate.
- */
- public int getX() {
- return x;
- }
-
- /**
- * Get the triad Y coordinate. Range: 0-255.
+ * The triad coordinate triple of the board.
*
- * @return Logical triad Y coordinate.
+ * @return Logical triad coordinates.
*/
- public int getY() {
- return y;
+ @JsonIgnore
+ public TriadCoords triad() {
+ return new TriadCoords(x, y, z);
}
/**
- * Get the triad Z coordinate. Range: 0-2.
+ * The physical coordinate triple of the board.
*
- * @return Logical triad Z coordinate.
+ * @return Physical board coordinates, or {@code null} if the {@link #board}
+ * is null.
*/
- public int getZ() {
- return z;
- }
-
- /**
- * Get the number of the cabinet containing the frame containing the board.
- *
- * @return Physical cabinet number.
- */
- public int getCabinet() {
- return cabinet;
- }
-
- /**
- * Get the number of the frame (within the cabinet) containing the board.
- *
- * @return Physical frame number.
- */
- public int getFrame() {
- return frame;
- }
-
- /**
- * Get the number of the board within its frame.
- *
- * @return Physical board number.
- */
- public int getBoard() {
- return board;
- }
-
- /**
- * Get the IP address of the Ethernet chip of the board, if available.
- *
- * @return IP address of ethernet chip. May be {@code null} if the
- * current user doesn't have permission to see the board address
- * at this point.
- */
- public String getAddress() {
- return address;
- }
-
- @Override
- public String toString() {
- return format("Board(%d,%d,%d|%d:%d:%d|%s)", x, y, z,
- cabinet, frame, board, address);
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof BoardCoords)) {
- return false;
+ @JsonIgnore
+ public PhysicalCoords physicalCoords() {
+ if (board == null) {
+ return null;
}
- var o = (BoardCoords) other;
- return x == o.x && y == o.y && z == o.z && cabinet == o.cabinet
- && frame == o.frame && Objects.equals(board, o.board)
- && Objects.equals(address, o.address);
+ return new PhysicalCoords(cabinet, frame, board);
}
@Override
- public int hashCode() {
- return (x << 16) | (y << 8) | z;
+ public String toString() {
+ return format("Board(%d,%d,%d|%d:%d:%d|%s)", x, y, z, cabinet, frame,
+ board, address);
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BriefMachineDescription.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BriefMachineDescription.java
index 0870de0038..f1b7781226 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BriefMachineDescription.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/BriefMachineDescription.java
@@ -23,7 +23,7 @@
import com.fasterxml.jackson.annotation.JsonAlias;
-class BriefMachineDescription {
+final class BriefMachineDescription {
/** The machine name. */
String name;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientSession.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientSession.java
index 93dff352b9..7bd8b72130 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientSession.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientSession.java
@@ -241,7 +241,12 @@ public void onWebsocketPong(WebSocket conn, Framedata f) {
}
private synchronized int issueCorrelationId() {
- return correlationCounter++;
+ int i = correlationCounter++;
+ if (i < 1) {
+ correlationCounter = 1;
+ i = 0;
+ }
+ return i;
}
/**
@@ -308,24 +313,30 @@ public void onMessage(ByteBuffer message) {
message.order(LITTLE_ENDIAN);
int code = message.getInt();
switch (ProxyProtocol.values()[code]) {
- case OPEN:
- case CLOSE:
- case OPEN_U:
+ case OPEN, CLOSE, OPEN_U ->
+ // Response to call
requireNonNull(replyHandlers.remove(message.getInt()),
"uncorrelated response").complete(message);
- break;
- case MSG:
+ case MSG ->
+ // Async message from board
requireNonNull(channels.get(message.getInt()),
"unrecognised channel").receive(message);
- break;
- case ERR:
- requireNonNull(replyHandlers.remove(message.getInt()),
- "uncorrelated response")
- .completeExceptionally(manufactureException(message));
- break;
- // case MSG_TO: // Never sent
- default:
- log.error("unexpected message code: {}", code);
+ case ERR -> {
+ // Error from call
+ int correlationId = message.getInt();
+ var exception = manufactureException(message);
+ if (correlationId < 0) {
+ // General error message
+ log.error("general failure reported by service", exception);
+ } else {
+ // Response to a particular call
+ requireNonNull(replyHandlers.remove(correlationId),
+ "uncorrelated response")
+ .completeExceptionally(exception);
+ }
+ }
+ // case MSG_TO -> // Never sent by service, only by us
+ default -> log.error("unexpected message code: {}", code);
}
}
@@ -419,9 +430,7 @@ private abstract class ChannelBase implements AutoCloseable {
* The message off the websocket.
*/
private void receive(ByteBuffer msg) {
- msg = msg.slice();
- msg.order(LITTLE_ENDIAN);
- receiveQueue.add(msg);
+ receiveQueue.add(msg.slice().order(LITTLE_ENDIAN));
}
/**
@@ -624,7 +633,7 @@ public synchronized boolean trackCookie(HttpURLConnection conn) {
var headerFields = conn.getHeaderFields();
var cookiesHeader = headerFields.get(SET_COOKIE);
if (cookiesHeader != null) {
- for (String setCookie : cookiesHeader) {
+ for (var setCookie : cookiesHeader) {
log.debug("Cookie header: {}", setCookie);
var m = SESSION_ID_RE.matcher(setCookie);
if (m.find()) {
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/CreateJob.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/CreateJob.java
index 97e097620b..f797462af7 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/CreateJob.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/CreateJob.java
@@ -21,14 +21,13 @@
import java.time.Duration;
import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.Positive;
-import javax.validation.constraints.PositiveOrZero;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.google.errorprone.annotations.Keep;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.AssertTrue;
+import jakarta.validation.constraints.Positive;
+import jakarta.validation.constraints.PositiveOrZero;
import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords;
import uk.ac.manchester.spinnaker.machine.board.TriadCoords;
import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber;
@@ -327,7 +326,7 @@ public CreateJob(int width, int height) {
* coordinates.
*/
public CreateJob(String machine, TriadCoords triad) {
- board = new SpecificBoard(true, triad.x, triad.y, triad.z);
+ board = new SpecificBoard(true, triad.x(), triad.y(), triad.z());
machineName = machine;
}
@@ -343,7 +342,8 @@ public CreateJob(String machine, TriadCoords triad) {
* The physical coordinates of the board to request.
*/
public CreateJob(String machine, PhysicalCoords coords) {
- this.board = new SpecificBoard(false, coords.c, coords.f, coords.b);
+ this.board =
+ new SpecificBoard(false, coords.c(), coords.f(), coords.b());
machineName = machine;
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java
index e8672ff1ea..a134dd1777 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java
@@ -20,7 +20,7 @@
import java.net.URI;
import java.util.List;
-class Jobs {
+final class Jobs {
/** The jobs of the machine. */
List jobs;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Machines.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Machines.java
index 781ca15c9f..b962cfe195 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Machines.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Machines.java
@@ -19,7 +19,7 @@
import java.util.List;
-class Machines {
+final class Machines {
/** The machine info. */
List machines;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Power.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Power.java
index 06d1be9527..a24c3b43b9 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Power.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Power.java
@@ -15,7 +15,7 @@
*/
package uk.ac.manchester.spinnaker.alloc.client;
-class Power {
+final class Power {
/** The power state. */
String power;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocol.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocol.java
index 4d05657a81..1aa976e606 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocol.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocol.java
@@ -15,7 +15,7 @@
*/
package uk.ac.manchester.spinnaker.alloc.client;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import java.nio.ByteBuffer;
@@ -51,7 +51,7 @@ enum ProxyProtocol {
* first word.
*/
ByteBuffer allocate() {
- var b = ByteBuffer.allocate(size).order(LITTLE_ENDIAN);
+ var b = alloc(size);
b.putInt(ordinal());
return b;
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/RootInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/RootInfo.java
index 9a2d95a67b..149f9610f1 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/RootInfo.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/RootInfo.java
@@ -21,7 +21,7 @@
import uk.ac.manchester.spinnaker.messages.model.Version;
-class RootInfo {
+final class RootInfo {
/** Service version. */
Version version;
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClient.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClient.java
index e62462aa48..51fe0d894d 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClient.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClient.java
@@ -22,14 +22,14 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.Serial;
import java.util.List;
import java.util.stream.Stream;
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-
import com.google.errorprone.annotations.MustBeClosed;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import uk.ac.manchester.spinnaker.machine.HasChipLocation;
import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords;
import uk.ac.manchester.spinnaker.machine.board.TriadCoords;
@@ -387,6 +387,7 @@ default void waitForPower() throws IOException {
* Exception caused by the server sending an error.
*/
class SpallocException extends RuntimeException {
+ @Serial
private static final long serialVersionUID = -1363689283367574333L;
/** The HTTP response code that triggered the exception. */
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClientFactory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClientFactory.java
index 9ea7e307fc..947954bd24 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClientFactory.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClientFactory.java
@@ -35,11 +35,9 @@
import static uk.ac.manchester.spinnaker.utils.InetFactory.getByNameQuietly;
import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO;
-import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
@@ -52,6 +50,7 @@
import java.util.Map;
import java.util.stream.Stream;
+import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import com.fasterxml.jackson.databind.json.JsonMapper;
@@ -147,9 +146,9 @@ public static Job getJobFromProxyInfo(ProxyInformation proxy)
if (proxy == null) {
return null;
}
- log.info("Using proxy {} for connections", proxy.spallocUrl);
- return new SpallocClientFactory(URI.create(proxy.spallocUrl))
- .getJob(proxy.jobUrl, proxy.headers, proxy.cookies);
+ log.info("Using proxy {} for connections", proxy.spallocUrl());
+ return new SpallocClientFactory(URI.create(proxy.spallocUrl()))
+ .getJob(proxy);
}
/**
@@ -167,16 +166,7 @@ public static Job getJobFromProxyInfo(ProxyInformation proxy)
* made into an instance of the given class.
*/
static T readJson(InputStream is, Class cls) throws IOException {
- BufferedReader streamReader = new BufferedReader(
- new InputStreamReader(is, "UTF-8"));
- StringBuilder responseStrBuilder = new StringBuilder();
-
- String inputStr;
- while ((inputStr = streamReader.readLine()) != null) {
- responseStrBuilder.append(inputStr);
- }
- String json = responseStrBuilder.toString();
-
+ var json = IOUtils.toString(is, UTF_8);
try {
return JSON_MAPPER.readValue(json, cls);
} catch (IOException e) {
@@ -301,26 +291,23 @@ public SpallocClient login(String username, String password)
/**
* Get direct access to a Job.
*
- * @param uri
- * The URI of the job
- * @param headers
- * The headers to read authentication from.
- * @param cookies
- * The cookies to read authentication from.
+ * @param proxyInfo
+ * The information (URL, headers, cookies) about the job.
* @return A job.
* @throws IOException
* If there is an error communicating with the server.
*/
- public Job getJob(String uri, Map headers,
- Map cookies) throws IOException {
- var u = URI.create(uri);
- var s = new ClientSession(baseUrl, headers, cookies);
+ private Job getJob(ProxyInformation proxyInfo) throws IOException {
+ var u = URI.create(proxyInfo.jobUrl());
+ var s = new ClientSession(baseUrl, proxyInfo.headers(),
+ proxyInfo.cookies());
var c = new ClientImpl(s, s.discoverRoot());
log.info("Connecting to job on {}", u);
return c.job(u);
}
- private abstract static class Common {
+ private abstract static sealed class Common
+ permits ClientImpl, JobImpl, MachineImpl {
private final SpallocClient client;
final Session s;
@@ -331,7 +318,7 @@ private abstract static class Common {
}
final Machine getMachine(String name) throws IOException {
- Machine m = MACHINE_MAP.get(name);
+ var m = MACHINE_MAP.get(name);
if (m == null) {
client.listMachines();
m = MACHINE_MAP.get(name);
@@ -373,7 +360,7 @@ private static final class ClientImpl extends Common
private URI machines;
- private ClientImpl(Session s, RootInfo ri) throws IOException {
+ private ClientImpl(Session s, RootInfo ri) {
super(null, s);
this.v = ri.version;
this.jobs = asDir(ri.jobsURI);
@@ -795,14 +782,14 @@ public void waitForChange() throws IOException {
public WhereIs getBoard(TriadCoords coords) throws IOException {
return whereis(
bmd.uri.resolve(format("logical-board?x=%d&y=%d&z=%d",
- coords.x, coords.y, coords.z)));
+ coords.x(), coords.y(), coords.z())));
}
@Override
public WhereIs getBoard(PhysicalCoords coords) throws IOException {
return whereis(bmd.uri.resolve(
format("physical-board?cabinet=%d&frame=%d&board=%d",
- coords.c, coords.f, coords.b)));
+ coords.c(), coords.f(), coords.b())));
}
@Override
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/BMPConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/BMPConnection.java
index 2785fdcf45..72158cf132 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/BMPConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/BMPConnection.java
@@ -56,11 +56,11 @@ public class BMPConnection extends UDPConnection
* If socket creation fails.
*/
public BMPConnection(BMPConnectionData connectionData) throws IOException {
- super(null, null, connectionData.ipAddress,
- (connectionData.portNumber == null ? SCP_SCAMP_PORT
- : connectionData.portNumber), IPTOS_RELIABILITY);
- coords = connectionData.bmp;
- boards = connectionData.boards;
+ super(null, null, connectionData.ipAddress(),
+ (connectionData.portNumber() == null ? SCP_SCAMP_PORT
+ : connectionData.portNumber()), IPTOS_RELIABILITY);
+ coords = connectionData.bmp();
+ boards = connectionData.boards();
}
@Override
@@ -105,7 +105,7 @@ public SCPResultMessage receiveSCPResponse(int timeout)
@Override
public SDPMessage receiveMessage(int timeout)
throws IOException, InterruptedException {
- return new SDPMessage(receive(timeout), true);
+ return new SDPMessage(receive(timeout));
}
/**
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/EIEIOConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/EIEIOConnection.java
index 888eb5a866..4064571716 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/EIEIOConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/EIEIOConnection.java
@@ -129,8 +129,8 @@ protected void sendCommand(EIEIOCommand command, InetAddress ipAddress,
protected EIEIOCommand receiveCommand()
throws IOException, InterruptedException {
var msg = receiveMessage();
- if (msg instanceof EIEIOCommandMessage) {
- return ((EIEIOCommandMessage) msg).getHeader().command;
+ if (msg instanceof EIEIOCommandMessage cmd) {
+ return cmd.getHeader().command;
}
throw new IOException("unexpected data message");
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/IPAddressConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/IPAddressConnection.java
index d350160442..91b7236bac 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/IPAddressConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/IPAddressConnection.java
@@ -84,7 +84,7 @@ public final InetAddress receiveMessage() {
public InetAddress receiveMessage(int timeout) {
try {
var packet = receiveWithAddress(timeout);
- var addr = packet.getAddress();
+ var addr = packet.address();
if (addr.getPort() == BOOTROM_SPINN_PORT) {
return addr.getAddress();
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/NotificationConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/NotificationConnection.java
index 98655f2874..ee53ce0770 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/NotificationConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/NotificationConnection.java
@@ -15,15 +15,12 @@
*/
package uk.ac.manchester.spinnaker.connections;
-import static java.nio.ByteBuffer.allocate;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static uk.ac.manchester.spinnaker.connections.UDPConnection.TrafficClass.IPTOS_RELIABILITY;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import java.io.IOException;
import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import uk.ac.manchester.spinnaker.messages.notification.AbstractNotificationMessage;
import uk.ac.manchester.spinnaker.messages.notification.NotificationMessage;
/**
@@ -94,14 +91,6 @@ public NotificationConnection(InetAddress localHost, Integer localPort,
setReceivePacketSize(NOTIFICATION_MESSAGE_BUFFER_SIZE);
}
- /**
- * @return Get a new little-endian buffer sized suitably for notification
- * messages.
- */
- private static ByteBuffer newMessageBuffer() {
- return allocate(NOTIFICATION_MESSAGE_BUFFER_SIZE).order(LITTLE_ENDIAN);
- }
-
/**
* Sends a notification message down this connection.
*
@@ -112,7 +101,7 @@ private static ByteBuffer newMessageBuffer() {
*/
public void sendNotification(NotificationMessage notificationMessage)
throws IOException {
- var b = newMessageBuffer();
+ var b = alloc(NOTIFICATION_MESSAGE_BUFFER_SIZE);
notificationMessage.addToBuffer(b);
b.flip();
send(b);
@@ -122,6 +111,6 @@ public void sendNotification(NotificationMessage notificationMessage)
public NotificationMessage receiveMessage(int timeout)
throws IOException, InterruptedException {
var b = receive(timeout);
- return AbstractNotificationMessage.build(b);
+ return NotificationMessage.build(b);
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/SDPConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/SDPConnection.java
index 00917766f3..ce2b285af4 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/SDPConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/SDPConnection.java
@@ -111,7 +111,7 @@ public SDPMessage receiveMessage(int timeout)
throws IOException, InterruptedIOException, InterruptedException {
var buffer = receive(timeout);
buffer.getShort(); // SKIP TWO PADDING BYTES
- return new SDPMessage(buffer, false);
+ return new SDPMessage(buffer);
}
/**
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPConnection.java
index 3840c1b6ac..031a66b281 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPConnection.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPConnection.java
@@ -17,9 +17,7 @@
import static java.lang.String.format;
import static java.net.InetAddress.getByAddress;
-import static java.nio.ByteBuffer.allocate;
import static java.nio.ByteBuffer.wrap;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static java.util.Objects.requireNonNullElse;
import static java.util.stream.Collectors.joining;
import static java.util.stream.IntStream.range;
@@ -28,6 +26,7 @@
import static uk.ac.manchester.spinnaker.messages.Constants.SCP_SCAMP_PORT;
import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_NOT_EXPECTED;
import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.RUNNING_COMMAND_SDP_PORT;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc;
import static uk.ac.manchester.spinnaker.utils.MathUtils.hexbyte;
import static uk.ac.manchester.spinnaker.utils.Ping.ping;
@@ -390,7 +389,7 @@ public final ByteBuffer receive(int timeout)
protected ByteBuffer doReceive(int timeout)
throws SocketTimeoutException, IOException, InterruptedException {
socket.setSoTimeout(timeout);
- var buffer = allocate(receivePacketSize);
+ var buffer = alloc(receivePacketSize);
var pkt = new DatagramPacket(buffer.array(), receivePacketSize);
socket.receive(pkt);
buffer.position(pkt.getLength()).flip();
@@ -399,7 +398,7 @@ protected ByteBuffer doReceive(int timeout)
pkt.getSocketAddress());
log.debug("message data: {}", describe(buffer));
}
- return buffer.order(LITTLE_ENDIAN);
+ return buffer;
}
@Override
@@ -430,7 +429,7 @@ public final UDPPacket receiveWithAddress(int timeout)
protected UDPPacket doReceiveWithAddress(int timeout)
throws SocketTimeoutException, IOException {
socket.setSoTimeout(timeout);
- var buffer = allocate(receivePacketSize);
+ var buffer = alloc(receivePacketSize);
var pkt = new DatagramPacket(buffer.array(), receivePacketSize);
socket.receive(pkt);
buffer.position(pkt.getLength()).flip();
@@ -439,7 +438,7 @@ protected UDPPacket doReceiveWithAddress(int timeout)
pkt.getSocketAddress());
log.debug("message data: {}", describe(buffer));
}
- return new UDPPacket(buffer.order(LITTLE_ENDIAN),
+ return new UDPPacket(buffer,
(InetSocketAddress) pkt.getSocketAddress());
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPPacket.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPPacket.java
index 95c66110ee..ab5f300fcc 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPPacket.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPPacket.java
@@ -20,38 +20,11 @@
/**
* A packet with an address.
+ *
+ * @param byteBuffer
+ * The buffer with the content of the packet.
+ * @param address
+ * The address that the packet came from or is going to.
*/
-public class UDPPacket {
- private final ByteBuffer byteBuffer;
-
- private final InetSocketAddress address;
-
- /**
- * Create a buffer with an address.
- *
- * @param byteBuffer
- * The buffer
- * @param address
- * The address
- */
- UDPPacket(ByteBuffer byteBuffer, InetSocketAddress address) {
- this.byteBuffer = byteBuffer;
- this.address = address;
- }
-
- /**
- * Get the buffer with the content of the packet.
- * @return The buffer
- */
- public ByteBuffer getByteBuffer() {
- return byteBuffer;
- }
-
- /**
- * Get the address.
- * @return The address
- */
- public InetSocketAddress getAddress() {
- return address;
- }
+public record UDPPacket(ByteBuffer byteBuffer, InetSocketAddress address) {
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/InvalidPacketException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/InvalidPacketException.java
deleted file mode 100644
index 36ace3d11e..0000000000
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/InvalidPacketException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2018 The University of Manchester
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package uk.ac.manchester.spinnaker.connections.model;
-
-import java.io.IOException;
-
-/**
- * Indicates that a packet with an unsupported format was received.
- *
- * @author Donal Fellows
- */
-public class InvalidPacketException extends IOException {
- private static final long serialVersionUID = -2509633246846245166L;
-
- /**
- * Create an instance.
- *
- * @param message
- * The exception message.
- */
- public InvalidPacketException(String message) {
- super(message);
- }
-
- /**
- * Create an instance.
- *
- * @param message
- * The exception message.
- * @param cause
- * The cause of the exception.
- */
- public InvalidPacketException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/MessageHandler.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/MessageHandler.java
index 9331ddf030..7b121fedcb 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/MessageHandler.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/MessageHandler.java
@@ -22,6 +22,7 @@
* the type of message handled.
* @author Donal Fellows
*/
+@FunctionalInterface
public interface MessageHandler {
/**
* The callback for handling the message.
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/SCPSenderReceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/SCPSenderReceiver.java
index 61380f160f..9dd13f2c2d 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/SCPSenderReceiver.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/SCPSenderReceiver.java
@@ -66,12 +66,9 @@ default ByteBuffer getSCPData(SCPRequest> scpRequest) {
default void send(SCPRequest> request) throws IOException {
var msg = getSCPData(request);
switch (request.sdpHeader.getFlags()) {
- case REPLY_EXPECTED:
- case REPLY_EXPECTED_NO_P2P:
+ case REPLY_EXPECTED, REPLY_EXPECTED_NO_P2P ->
send(msg, request.scpRequestHeader.getSequence());
- break;
- default:
- send(msg);
+ default -> send(msg);
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/Utils.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/Utils.java
deleted file mode 100644
index be6330f036..0000000000
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/Utils.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2023 The University of Manchester
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package uk.ac.manchester.spinnaker.messages;
-
-import static java.nio.ByteBuffer.allocate;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
-import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE;
-
-import java.nio.ByteBuffer;
-
-/**
- * Utilities for working with messages.
- */
-public abstract class Utils {
- private Utils() {
- }
-
- /**
- * Convert a word to a buffer that could form part of a message understood
- * by SpiNNaker.
- *
- * @param value
- * The value to put in the buffer as a single 32-bit word.
- * @return The buffer, flipped. The buffer is writable and has a backing
- * array.
- */
- public static ByteBuffer wordAsBuffer(int value) {
- ByteBuffer b = allocate(WORD_SIZE).order(LITTLE_ENDIAN);
- b.putInt(value).flip();
- return b;
- }
-}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPRequest.java
index 4cf6b75665..5a69f447c5 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPRequest.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPRequest.java
@@ -41,19 +41,24 @@
* @param
* The type of the response to the request.
*/
-public abstract class BMPRequest
- extends SCPRequest {
+public abstract sealed class BMPRequest
+ extends SCPRequest
+ permits EraseFlash, GetBMPVersion, GetFPGAResetStatus, InitFPGA,
+ ReadADC, ReadBMPMemory, ReadCANStatus, ReadFPGARegister, ReadIPAddress,
+ ReadSerialFlash, ReadSerialFlashCRC, ReadSerialVector, ResetFPGA,
+ SetBoardLEDs, SetPower, UpdateFlash, WriteBMPMemory, WriteFlashBuffer,
+ WriteFPGAData, WriteFPGARegister, WriteSerialFlash {
private static SDPHeader header(int board) {
return new SDPHeader(REPLY_EXPECTED, new SDPLocation(0, 0, board),
DEFAULT_PORT);
}
private static SDPHeader header(BMPBoard board) {
- return header(board.board);
+ return header(board.board());
}
private static SDPHeader header(Collection boards) {
- return header(boards.stream().mapToInt(b -> b.board).min().orElse(0));
+ return header(boards.stream().mapToInt(b -> b.board()).min().orElse(0));
}
/**
@@ -172,7 +177,7 @@ private static SDPHeader header(Collection boards) {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder();
+ var builder = new StringBuilder();
builder.append(getClass().getSimpleName());
builder.append('(');
builder.append("command=");
@@ -197,7 +202,8 @@ public String toString() {
* @see CheckOKResponse
*/
@UsedInJavadocOnly(CheckOKResponse.class)
- public static class BMPResponse extends SCPResponse {
+ public static sealed class BMPResponse extends SCPResponse
+ permits PayloadedResponse {
/**
* Make a response object.
*
@@ -223,8 +229,14 @@ public BMPResponse(String operation, SCPCommand command,
* @param
* The type of the parsed payload.
*/
- public abstract static class PayloadedResponse extends BMPResponse
- implements Supplier {
+ public abstract static sealed class PayloadedResponse extends BMPResponse
+ implements Supplier
+ permits EraseFlash.Response, GetBMPVersion.Response,
+ GetFPGAResetStatus.Response, ReadADC.Response,
+ ReadBMPMemory.Response, ReadCANStatus.Response,
+ ReadFPGARegister.Response, ReadIPAddress.Response,
+ ReadSerialFlash.Response, ReadSerialFlashCRC.Response,
+ ReadSerialVector.Response {
private final T value;
/**
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/EraseFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/EraseFlash.java
index 117a8bf1d2..60ae74208b 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/EraseFlash.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/EraseFlash.java
@@ -46,13 +46,13 @@ public final class EraseFlash extends BMPRequest {
* If the baseAddress or size make no sense
*/
public EraseFlash(BMPBoard board, MemoryLocation baseAddress, int size) {
- super(board, CMD_FLASH_ERASE, baseAddress.address,
- baseAddress.address + size);
+ super(board, CMD_FLASH_ERASE, baseAddress.address(),
+ baseAddress.address() + size);
// Check that we've been actually asked to do something sane!
if (size <= 0) {
throw new IllegalArgumentException("no data");
}
- int addr = baseAddress.address;
+ int addr = baseAddress.address();
if (addr < 0 || addr + size > MEMORY_LIMIT || addr + size < 0) {
throw new IllegalArgumentException("address not in flash");
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java
index 9b4442afa4..9071a8c8ad 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java
@@ -29,7 +29,7 @@
*
* Calls or {@code cmd_ver()} in {@code bmp_cmd.c}.
*/
-public class GetBMPVersion extends BMPRequest {
+public final class GetBMPVersion extends BMPRequest {
/**
* @param board
* The board to get the version from
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetFPGAResetStatus.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetFPGAResetStatus.java
index 6e57a32c42..77a22ffbd3 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetFPGAResetStatus.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetFPGAResetStatus.java
@@ -32,7 +32,7 @@
* Calls {@code cmd_read()} in {@code bmp_cmd.c} with special parameters and
* parses the result.
*/
-public class GetFPGAResetStatus
+public final class GetFPGAResetStatus
extends BMPRequest {
/**
* @param board
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/InitFPGA.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/InitFPGA.java
index 41e72d9491..a050c496e6 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/InitFPGA.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/InitFPGA.java
@@ -28,7 +28,7 @@
*
* Calls {@code fpga_init()} in {@code bmp_hw.c}.
*/
-public class InitFPGA extends BMPRequest {
+public final class InitFPGA extends BMPRequest {
/**
* @param board
* Which board's FPGA to initialise.
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadADC.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadADC.java
index f234476aa8..b4317ad4ef 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadADC.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadADC.java
@@ -39,7 +39,7 @@
* monitoring of these values is done in {@code check_status()} in
* {@code bmp_main.c}.
*/
-public class ReadADC extends BMPRequest {
+public final class ReadADC extends BMPRequest {
/**
* @param board
* which board to request the ADC register from
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPReadMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java
similarity index 89%
rename from SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPReadMemory.java
rename to SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java
index 39fefa4ee3..df5eac5e6b 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPReadMemory.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java
@@ -15,10 +15,10 @@
*/
package uk.ac.manchester.spinnaker.messages.bmp;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE;
import static uk.ac.manchester.spinnaker.messages.model.TransferUnit.efficientTransferUnit;
import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_READ;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly;
import java.nio.ByteBuffer;
@@ -32,7 +32,7 @@
*
* Calls {@code cmd_read()} in {@code bmp_cmd.c}.
*/
-public class BMPReadMemory extends BMPRequest {
+public final class ReadBMPMemory extends BMPRequest {
private static int validate(int size) {
if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) {
throw new IllegalArgumentException(
@@ -49,8 +49,8 @@ private static int validate(int size) {
* @param size
* The number of bytes to read, between 1 and 256
*/
- public BMPReadMemory(BMPBoard board, MemoryLocation address, int size) {
- super(board, CMD_READ, address.address, validate(size),
+ public ReadBMPMemory(BMPBoard board, MemoryLocation address, int size) {
+ super(board, CMD_READ, address.address(), validate(size),
efficientTransferUnit(address, size).value);
}
@@ -73,7 +73,7 @@ protected final class Response
/** @return The data read, in a little-endian read-only buffer. */
@Override
protected ByteBuffer parse(ByteBuffer buffer) {
- return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN);
+ return readOnly(buffer);
}
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadCANStatus.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadCANStatus.java
index 796cde1d82..d5c925e9de 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadCANStatus.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadCANStatus.java
@@ -34,7 +34,7 @@
* Handled in {@code cmd_bmp_info()} (in {@code bmp_cmd.c}) by reading from
* {@code can_status}.
*/
-public class ReadCANStatus extends BMPRequest {
+public final class ReadCANStatus extends BMPRequest {
private static final int MAX_BOARDS_PER_FRAME = 24;
private static final BMPBoard FRAME_ROOT = new BMPBoard(0);
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadFPGARegister.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadFPGARegister.java
index 35395fbc8a..1fbdf5a7d1 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadFPGARegister.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadFPGARegister.java
@@ -31,7 +31,8 @@
*
* Calls {@code cmd_fpga_read()} in {@code bmp_cmd.c}.
*/
-public class ReadFPGARegister extends BMPRequest {
+public final class ReadFPGARegister
+ extends BMPRequest {
/**
* @param fpga
* FPGA (0, 1 or 2 on SpiNN-5 board) to communicate with.
@@ -45,7 +46,7 @@ public class ReadFPGARegister extends BMPRequest {
*/
public ReadFPGARegister(FPGA fpga, MemoryLocation register,
BMPBoard board) {
- super(board, CMD_FPGA_READ, register.address, WORD_SIZE, fpga.value);
+ super(board, CMD_FPGA_READ, register.address(), WORD_SIZE, fpga.value);
if (!register.isAligned()) {
throw new IllegalArgumentException(
"FPGA register addresses must be aligned");
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadIPAddress.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadIPAddress.java
index 5eb979c88c..6e3555995b 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadIPAddress.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadIPAddress.java
@@ -15,6 +15,7 @@
*/
package uk.ac.manchester.spinnaker.messages.bmp;
+import static java.lang.System.arraycopy;
import static java.net.InetAddress.getByAddress;
import static uk.ac.manchester.spinnaker.messages.bmp.BMPInfo.IP_ADDR;
import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_BMP_INFO;
@@ -34,7 +35,7 @@
*
* Handled by {@code cmd_bmp_info()} in {@code bmp_cmd.c}.
*/
-public class ReadIPAddress extends BMPRequest {
+public final class ReadIPAddress extends BMPRequest {
/**
* @param board
* which board to request the IP address data from
@@ -48,6 +49,34 @@ public Response getSCPResponse(ByteBuffer buffer) throws Exception {
return new Response(buffer);
}
+ private static final int CHUNK_LEN = 32;
+
+ private static final int IP_OFFSET = 8;
+
+ private static final int IP_LEN = 4;
+
+ /**
+ * Get a slice out of the result buffer and pick the IP address out of that.
+ *
+ * @param buffer
+ * The result buffer. Position will be updated.
+ * @return The parsed IP address.
+ * @throws UnknownHostException
+ * Unexpected; we are presenting the right number of bytes.
+ */
+ private static InetAddress getIP(ByteBuffer buffer)
+ throws UnknownHostException {
+ /*
+ * NB: CHUNK_LEN != IP_LEN so we *must* copy like this or otherwise
+ * mess around with the buffer position. This is easiest.
+ */
+ var chunk = new byte[CHUNK_LEN];
+ buffer.get(chunk);
+ var bytes = new byte[IP_LEN];
+ arraycopy(chunk, IP_OFFSET, bytes, 0, IP_LEN);
+ return getByAddress(bytes);
+ }
+
/** An SCP response to a request for IP address information. */
protected final class Response
extends BMPRequest.PayloadedResponse {
@@ -56,25 +85,11 @@ private Response(ByteBuffer buffer)
super("Read IP Address Data", CMD_BMP_INFO, buffer);
}
- private static final int CHUNK_LEN = 32;
-
- private static final int IP_OFFSET = 8;
-
- private static final int IP_LEN = 4;
-
- private InetAddress getIP(ByteBuffer buffer)
- throws UnknownHostException {
- byte[] chunk = new byte[CHUNK_LEN];
- buffer.get(chunk);
- byte[] bytes = new byte[IP_LEN];
- System.arraycopy(chunk, IP_OFFSET, bytes, 0, IP_LEN);
- return getByAddress(bytes);
- }
-
/** @return The addresses of the SpiNNaker board. */
@Override
protected Addresses parse(ByteBuffer buffer) {
try {
+ // Tricky point: order of evaluation matters
return new Addresses(getIP(buffer), getIP(buffer));
} catch (UnknownHostException e) {
// Should be unreachable
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java
index 95424657cd..7e4071049c 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java
@@ -15,10 +15,10 @@
*/
package uk.ac.manchester.spinnaker.messages.bmp;
-import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE;
import static uk.ac.manchester.spinnaker.messages.bmp.SerialFlashOp.READ;
import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_BMP_SF;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly;
import java.nio.ByteBuffer;
@@ -32,7 +32,8 @@
*
* Calls {@code sf_read()} in {@code bmp_ssp.c}.
*/
-public class ReadSerialFlash extends BMPRequest {
+public final class ReadSerialFlash
+ extends BMPRequest {
private static int validate(int size) {
if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) {
throw new IllegalArgumentException(
@@ -50,7 +51,7 @@ private static int validate(int size) {
* The number of bytes to read, between 1 and 256
*/
public ReadSerialFlash(BMPBoard board, MemoryLocation address, int size) {
- super(board, CMD_BMP_SF, address.address, validate(size), READ.value);
+ super(board, CMD_BMP_SF, address.address(), validate(size), READ.value);
}
@Override
@@ -72,7 +73,7 @@ protected final class Response
/** @return The data read, in a little-endian read-only buffer. */
@Override
protected ByteBuffer parse(ByteBuffer buffer) {
- return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN);
+ return readOnly(buffer);
}
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlashCRC.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlashCRC.java
index 21cfb51ccc..981b31e080 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlashCRC.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlashCRC.java
@@ -30,7 +30,7 @@
*
* Calls {@code sf_crc32()} in {@code bmp_ssp.c}.
*/
-public class ReadSerialFlashCRC
+public final class ReadSerialFlashCRC
extends BMPRequest {
/**
* @param board
@@ -42,7 +42,7 @@ public class ReadSerialFlashCRC
*/
public ReadSerialFlashCRC(BMPBoard board, MemoryLocation baseAddress,
int size) {
- super(board, CMD_BMP_SF, baseAddress.address, size, CRC.value);
+ super(board, CMD_BMP_SF, baseAddress.address(), size, CRC.value);
}
@Override
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialVector.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialVector.java
index f6e7d7bc29..1f79fb30d7 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialVector.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialVector.java
@@ -16,11 +16,15 @@
package uk.ac.manchester.spinnaker.messages.bmp;
import static uk.ac.manchester.spinnaker.messages.bmp.BMPInfo.SERIAL;
+import static uk.ac.manchester.spinnaker.messages.model.SerialVector.SERIAL_LENGTH;
import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_BMP_INFO;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import uk.ac.manchester.spinnaker.machine.MemoryLocation;
import uk.ac.manchester.spinnaker.machine.board.BMPBoard;
+import uk.ac.manchester.spinnaker.messages.model.SerialVector;
import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException;
/**
@@ -29,7 +33,8 @@
*
* Handled by {@code cmd_bmp_info()} in {@code bmp_cmd.c}.
*/
-public class ReadSerialVector extends BMPRequest {
+public final class ReadSerialVector
+ extends BMPRequest {
/**
* @param board
* which board to request the serial data from
@@ -54,7 +59,16 @@ private Response(ByteBuffer buffer)
/** @return The serial data. */
@Override
protected SerialVector parse(ByteBuffer buffer) {
- return new SerialVector(buffer);
+ var b = buffer.asIntBuffer();
+ var hardwareVersion = b.get();
+ var sn = new int[SERIAL_LENGTH];
+ b.get(sn);
+ var serialNumber = IntBuffer.wrap(sn);
+ var flashBuffer = new MemoryLocation(b.get());
+ var boardStat = new MemoryLocation(b.get());
+ var cortexBoot = new MemoryLocation(b.get());
+ return new SerialVector(hardwareVersion, serialNumber, flashBuffer,
+ boardStat, cortexBoot);
}
}
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ResetFPGA.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ResetFPGA.java
index f2fb5d61ba..33d288edd0 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ResetFPGA.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ResetFPGA.java
@@ -29,7 +29,7 @@
*
* Calls {@code fpga_reset()} in {@code bmp_hw.c}.
*/
-public class ResetFPGA extends BMPRequest {
+public final class ResetFPGA extends BMPRequest {
/**
* @param board
* Which board to reset the FPGAs of.
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPSetLED.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.java
similarity index 90%
rename from SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPSetLED.java
rename to SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.java
index 4afc48d379..76e86ca839 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPSetLED.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.java
@@ -33,7 +33,7 @@
* Handled by {@code cmp_led()} in {@code bmp_cmd.c}.
*/
@UsedInJavadocOnly(SetLED.class)
-public class BMPSetLED extends BMPRequest {
+public final class SetBoardLEDs extends BMPRequest {
/**
* Make a request.
*
@@ -44,7 +44,7 @@ public class BMPSetLED extends BMPRequest {
* @param boards
* The boards to talk to
*/
- public BMPSetLED(Collection leds, LEDAction action,
+ public SetBoardLEDs(Collection leds, LEDAction action,
Collection boards) {
super(boards, CMD_LED, argument1(action, leds), argument2(boards));
}
@@ -54,7 +54,7 @@ private static int argument1(LEDAction action, Collection leds) {
}
private static int argument2(Collection boards) {
- return boards.stream().mapToInt(board -> 1 << board.board).sum();
+ return boards.stream().mapToInt(board -> 1 << board.board()).sum();
}
@Override
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetPower.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetPower.java
index aa6166b64e..4729fee2e1 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetPower.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetPower.java
@@ -35,7 +35,7 @@
* Handled by {@code cmd_power()} in {@code bmp_cmd.c}, which in turn calls
* {@code proc_power()} in the same file.
*/
-public class SetPower extends BMPRequest {
+public final class SetPower extends BMPRequest {
private static final int DELAY_SHIFT = 16;
private static final BMPBoard FRAME_ROOT = new BMPBoard(0);
@@ -61,7 +61,7 @@ private static int argument1(double delay, PowerCommand powerCommand) {
}
private static int boardMask(Collection boards) {
- return boards.stream().mapToInt(board -> 1 << board.board).sum();
+ return boards.stream().mapToInt(board -> 1 << board.board()).sum();
}
@Override
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/UpdateFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/UpdateFlash.java
index 037c788e74..7b23258ca6 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/UpdateFlash.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/UpdateFlash.java
@@ -41,7 +41,7 @@ public final class UpdateFlash extends BMPRequest {
* The number of bytes to copy
*/
public UpdateFlash(BMPBoard board, MemoryLocation baseAddress, int size) {
- super(board, CMD_FLASH_COPY, REAL_FLASH_ADDRESS, baseAddress.address,
+ super(board, CMD_FLASH_COPY, REAL_FLASH_ADDRESS, baseAddress.address(),
size);
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPWriteMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java
similarity index 89%
rename from SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPWriteMemory.java
rename to SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java
index da7bb2e29f..1255f105dd 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPWriteMemory.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java
@@ -28,7 +28,7 @@
*
* Calls {@code cmd_write()} in {@code bmp_cmd.c}.
*/
-public class BMPWriteMemory extends BMPRequest {
+public final class WriteBMPMemory extends BMPRequest {
/**
* @param board
* the board with the BMP to write the memory of
@@ -40,9 +40,9 @@ public class BMPWriteMemory extends BMPRequest {
* must extend up to the limit. The position and limit of
* the buffer will not be updated by this constructor.
*/
- public BMPWriteMemory(BMPBoard board, MemoryLocation baseAddress,
+ public WriteBMPMemory(BMPBoard board, MemoryLocation baseAddress,
ByteBuffer data) {
- super(board, CMD_WRITE, baseAddress.address, data.remaining(),
+ super(board, CMD_WRITE, baseAddress.address(), data.remaining(),
efficientTransferUnit(baseAddress, data.remaining()).value,
data);
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGAData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGAData.java
index 0af192e764..0358e62b45 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGAData.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGAData.java
@@ -29,7 +29,7 @@
*
* Calls {@code ssp1_copy()} in {@code bmp_ssp.c}.
*/
-public class WriteFPGAData extends BMPRequest {
+public final class WriteFPGAData extends BMPRequest {
/**
* @param board
* Which board to upload the FPGA data to.
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java
index 4d2540538b..8716424d5b 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java
@@ -16,8 +16,8 @@
package uk.ac.manchester.spinnaker.messages.bmp;
import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE;
-import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer;
import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_FPGA_WRITE;
+import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.wordAsBuffer;
import java.nio.ByteBuffer;
@@ -37,7 +37,8 @@
* @see The SpI/O project
* on GitHub
*/
-public class WriteFPGARegister extends BMPRequest {
+public final class WriteFPGARegister
+ extends BMPRequest {
/**
* @param fpga
* FPGA (0, 1 or 2 on SpiNN-5 board) to communicate with.
@@ -53,7 +54,7 @@ public class WriteFPGARegister extends BMPRequest {
*/
public WriteFPGARegister(FPGA fpga, MemoryLocation register, int value,
BMPBoard board) {
- super(board, CMD_FPGA_WRITE, register.address, WORD_SIZE, fpga.value,
+ super(board, CMD_FPGA_WRITE, register.address(), WORD_SIZE, fpga.value,
wordAsBuffer(value));
if (!register.isAligned()) {
throw new IllegalArgumentException(
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFlashBuffer.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFlashBuffer.java
index 5f9a8df339..bcd74fc636 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFlashBuffer.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFlashBuffer.java
@@ -28,7 +28,7 @@
*
* Calls {@code cmd_flash_write()} in {@code bmp_cmd.c}.
*/
-public class WriteFlashBuffer extends BMPRequest {
+public final class WriteFlashBuffer extends BMPRequest {
/** The size of chunk that will be transferred. Fixed. */
public static final int FLASH_CHUNK_SIZE = 4096;
@@ -42,7 +42,7 @@ public class WriteFlashBuffer extends BMPRequest {
*/
public WriteFlashBuffer(BMPBoard board, MemoryLocation baseAddress,
boolean erase) {
- super(board, CMD_FLASH_WRITE, baseAddress.address, FLASH_CHUNK_SIZE,
+ super(board, CMD_FLASH_WRITE, baseAddress.address(), FLASH_CHUNK_SIZE,
erase ? 1 : 0);
}
diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteSerialFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteSerialFlash.java
index 1fb553f5c1..56afbbc762 100644
--- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteSerialFlash.java
+++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteSerialFlash.java
@@ -29,7 +29,7 @@
*
* Calls {@code sf_write()} in {@code bmp_ssp.c}.
*/
-public class WriteSerialFlash extends BMPRequest {
+public final class WriteSerialFlash extends BMPRequest {
/** The size of chunk that will be transferred. Fixed. */
public static final int FLASH_CHUNK_SIZE = 256;
@@ -45,7 +45,7 @@ public class WriteSerialFlash extends BMPRequest |