From 83f029595a7955fb42ac41e07335ff81cb17f820 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 21 Nov 2022 14:59:26 +0000 Subject: [PATCH 001/194] Update Java version --- .github/workflows/build.yml | 14 +++++----- .github/workflows/publish-pkgs.yml | 2 +- .github/workflows/publish.yml | 2 +- pom.xml | 42 +++--------------------------- 4 files changed, 12 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0278a5eb2a..4cad10edc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: # Minimum Java version! - java: [11] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [11, 14, 17] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK @@ -78,8 +78,8 @@ jobs: CI_BUILD_URL: https://github.com/${{ github.repository }}/commit/${{ github.event.after }}/checks COVERALLS_SECRET: ${{ secrets.GITHUB_TOKEN }} continue-on-error: true - - name: Upload Build (JDK 11 only) - if: matrix.java == 11 + - name: Upload Build (JDK 17 only) + if: matrix.java == 17 uses: actions/upload-artifact@v3 with: name: spinnaker-exe.jar @@ -91,7 +91,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [11, 14] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} @@ -113,11 +113,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3.6.0 with: distribution: 'zulu' - java-version: 11 + java-version: 17 cache: 'maven' - name: "Check: No FIXMEs left" diff --git a/.github/workflows/publish-pkgs.yml b/.github/workflows/publish-pkgs.yml index 3cb9c63bc8..efd41cb300 100644 --- a/.github/workflows/publish-pkgs.yml +++ b/.github/workflows/publish-pkgs.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-java@v3.6.0 with: - java-version: '11' + java-version: '17' distribution: 'zulu' - name: Publish package run: mvn --batch-mode deploy diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 36ba7ced35..0db9223d5a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [14] + java: [17] env: SETTINGS_FILE: .github/settings.xml SITE_DIR: target/staging diff --git a/pom.xml b/pom.xml index 656d95c7be..2b6141c6b8 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ along with this program. If not, see . UTF-8 - 11 + 17 true true @@ -471,10 +471,8 @@ along with this program. If not, see . https://docs.spring.io/spring-framework/docs/current/javadoc-api/ https://docs.spring.io/spring-security/site/docs/current/api/ https://docs.spring.io/spring-boot/docs/current/api/ - https://jakarta.ee/specifications/servlet/4.0/apidocs/ + https://cxf.apache.org/javadoc/latest-3.0.x/ https://errorprone.info/api/latest/ https://fasterxml.github.io/jackson-core/javadoc/${jackson.doc.version}/ https://fasterxml.github.io/jackson-databind/javadoc/${jackson.doc.version}/ @@ -739,6 +737,7 @@ along with this program. If not, see . SpiNNaker-front-end SpiNNaker-allocserv SpiNNaker-py2json + keycloak-management-client SpiNNaker Java Host Implementation of the host software for SpiNNaker in Java. @@ -954,13 +953,6 @@ along with this program. If not, see . - - - KeycloakClient - - keycloak-management-client - - CheckForFIXME @@ -998,34 +990,6 @@ along with this program. If not, see . - - Java17extras - - [17,) - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - - https://docs.spring.io/spring-framework/docs/current/javadoc-api/ - https://docs.spring.io/spring-security/site/docs/current/api/ - https://docs.spring.io/spring-boot/docs/current/api/ - https://jakarta.ee/specifications/servlet/4.0/apidocs/ - https://cxf.apache.org/javadoc/latest-3.0.x/ - https://errorprone.info/api/latest/ - https://fasterxml.github.io/jackson-core/javadoc/${jackson.doc.version}/ - https://fasterxml.github.io/jackson-databind/javadoc/${jackson.doc.version}/ - https://www.slf4j.org/api/ - - - - - - ErrorProne From 6c52aab88a0a387235f3cc3c8fb2783873d24925 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 21 Nov 2022 15:01:03 +0000 Subject: [PATCH 002/194] Bump spring.version from 5.3.23 to 6.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2b6141c6b8..c2795ecd36 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ along with this program. If not, see . 2.0.4 2.19.0 - 5.3.23 + 6.0.0 2.7.5 - 5.7.5 + 6.0.0 3.5.4 2.14.0 @@ -283,9 +283,19 @@ along with this program. If not, see . ${spring.security.version} - javax - javaee-api - 8.0.1 + org.springframework.security + spring-security-config + ${spring.security.version} + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + jakarta.mail + jakarta.mail-api + 2.1.0 org.apache.cxf From f191b88b41142f7fd6da3d38740cc6862853c512 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 25 Nov 2022 13:53:31 +0000 Subject: [PATCH 004/194] Much of the migration done Might need fixing for validation (which would be update dependency versions and changing "javax" to "jakarta" in a bunch of places). But that's not critical yet because we're still blocked on CXF-8371 https://issues.apache.org/jira/projects/CXF/issues/CXF-8371 --- SpiNNaker-allocserv/pom.xml | 8 +++- .../spinnaker/alloc/ServiceConfig.java | 20 +++++----- .../spinnaker/alloc/admin/AdminAPI.java | 32 ++++++++-------- .../spinnaker/alloc/admin/AdminImpl.java | 23 ++++++----- .../alloc/admin/MachineDefinitionLoader.java | 2 +- .../alloc/admin/MachineStateControl.java | 4 +- .../alloc/admin/ReportMailSender.java | 3 +- .../alloc/allocator/ProxyRememberer.java | 3 +- .../spinnaker/alloc/bmp/BMPController.java | 5 +-- .../spinnaker/alloc/bmp/FirmwareLoader.java | 3 +- .../alloc/bmp/PhysicalSerialMapping.java | 6 +-- .../spinnaker/alloc/bmp/SpiNNaker1.java | 3 +- .../alloc/bmp/TransceiverFactory.java | 5 +-- .../alloc/compat/V1CompatService.java | 5 +-- .../spinnaker/alloc/compat/V1TaskImpl.java | 3 +- .../alloc/db/DataAccessExceptionMapper.java | 11 +++--- .../spinnaker/alloc/db/DatabaseCache.java | 4 +- .../spinnaker/alloc/db/DatabaseEngine.java | 5 +-- .../alloc/db/SQLExceptionMapper.java | 11 +++--- .../spinnaker/alloc/proxy/SpinWSHandler.java | 7 ++-- .../security/AccessDeniedExceptionMapper.java | 17 ++++----- .../alloc/security/BasicAuthEntryPoint.java | 7 ++-- .../alloc/security/LocalAuthProviderImpl.java | 2 +- .../MyAuthenticationFailureHandler.java | 7 ++-- .../alloc/security/PasswordServices.java | 4 +- .../spinnaker/alloc/security/Permit.java | 2 +- .../alloc/security/SecurityConfig.java | 10 ++--- .../alloc/web/BackgroundSupport.java | 5 +-- .../alloc/web/CreateJobResponse.java | 3 +- .../spinnaker/alloc/web/JobStateResponse.java | 3 +- .../spinnaker/alloc/web/ListJobsResponse.java | 3 +- .../spinnaker/alloc/web/MachineResponse.java | 3 +- .../spinnaker/alloc/web/MachinesResponse.java | 3 +- .../alloc/web/RequestFailedException.java | 30 +++++++-------- .../alloc/web/ServiceDescription.java | 5 +-- .../alloc/web/SpallocServiceAPI.java | 38 +++++++++---------- .../web/SpallocServiceAPIImplBuilder.java | 11 +++--- .../alloc/web/SpallocServiceImpl.java | 22 +++++------ .../alloc/web/SubMachineResponse.java | 3 +- .../spinnaker/alloc/web/SystemController.java | 4 +- .../alloc/web/SystemControllerImpl.java | 4 +- .../spinnaker/alloc/web/WhereIsResponse.java | 3 +- .../spinnaker/alloc/web/JsonTest.java | 9 ++--- .../spinnaker/alloc/web/StubUriInfo.java | 8 ++-- 44 files changed, 172 insertions(+), 197 deletions(-) diff --git a/SpiNNaker-allocserv/pom.xml b/SpiNNaker-allocserv/pom.xml index 698ea0b0f1..16c622c38d 100644 --- a/SpiNNaker-allocserv/pom.xml +++ b/SpiNNaker-allocserv/pom.xml @@ -428,8 +428,12 @@ along with this program. If not, see . jakarta.servlet.jsp.jstl - javax.servlet - jstl + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + + + org.glassfish.web + jakarta.servlet.jsp.jstl org.springframework.security diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java index ec5c38ddfd..abe9e82f3a 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java @@ -20,9 +20,9 @@ import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; import static java.lang.System.setProperty; import static java.util.concurrent.Executors.newScheduledThreadPool; -import static javax.ws.rs.core.MediaType.TEXT_PLAIN; -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.status; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; import static org.apache.cxf.message.Message.PROTOCOL_HEADERS; import static org.apache.cxf.phase.Phase.RECEIVE; import static org.apache.cxf.transport.http.AbstractHTTPDestination.HTTP_REQUEST; @@ -36,14 +36,13 @@ import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.PostConstruct; -import javax.servlet.ServletRequest; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.ServletRequest; import javax.validation.ValidationException; -import javax.ws.rs.ApplicationPath; -import javax.ws.rs.core.Application; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.endpoint.Server; @@ -78,6 +77,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import jakarta.ws.rs.ext.Provider; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AllocatorProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AuthProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.HistoricalDataProperties; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java index fec6958bc9..f2805208c1 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java @@ -16,10 +16,10 @@ */ package uk.ac.manchester.spinnaker.alloc.admin; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; import static java.util.Objects.nonNull; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.MediaType.TEXT_PLAIN; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static uk.ac.manchester.spinnaker.alloc.admin.AdminAPI.Paths.BOARD; import static uk.ac.manchester.spinnaker.alloc.admin.AdminAPI.Paths.GROUP; import static uk.ac.manchester.spinnaker.alloc.admin.AdminAPI.Paths.IMPORT; @@ -34,23 +34,23 @@ import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -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.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.SecurityContext; -import javax.ws.rs.core.UriInfo; import org.springframework.security.access.prepost.PreAuthorize; import io.swagger.v3.oas.annotations.Hidden; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +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.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.alloc.model.GroupRecord; import uk.ac.manchester.spinnaker.alloc.model.MemberRecord; import uk.ac.manchester.spinnaker.alloc.model.UserRecord; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java index 8cac00a302..eca4cb6323 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java @@ -16,13 +16,13 @@ */ package uk.ac.manchester.spinnaker.alloc.admin; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.Response.created; +import static jakarta.ws.rs.core.Response.noContent; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; +import static jakarta.ws.rs.core.Response.Status.NOT_MODIFIED; import static java.util.stream.Collectors.toList; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.Response.created; -import static javax.ws.rs.core.Response.noContent; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.NOT_MODIFIED; import static org.slf4j.LoggerFactory.getLogger; import static uk.ac.manchester.spinnaker.alloc.admin.AdminAPI.Paths.BASE_PATH; @@ -30,12 +30,6 @@ import java.net.URI; import java.util.Map; -import javax.ws.rs.Path; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.SecurityContext; -import javax.ws.rs.core.UriInfo; - import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jmx.export.annotation.ManagedOperation; @@ -43,6 +37,11 @@ import org.springframework.stereotype.Service; import io.swagger.v3.oas.annotations.Hidden; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.SecurityContext; +import jakarta.ws.rs.core.UriInfo; import uk.ac.manchester.spinnaker.alloc.admin.MachineDefinitionLoader.Machine; import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; import uk.ac.manchester.spinnaker.alloc.model.MemberRecord; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 1d7280e530..8c91aa9c08 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -35,7 +35,6 @@ import java.util.Optional; import java.util.Set; -import javax.annotation.PostConstruct; import javax.validation.Valid; import javax.validation.ValidatorFactory; import javax.validation.constraints.AssertFalse; @@ -61,6 +60,7 @@ import com.google.errorprone.annotations.Keep; import com.google.errorprone.annotations.RestrictedApi; +import jakarta.annotation.PostConstruct; import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Update; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index b724ab2c0c..bfb7886ccf 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -40,8 +40,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.function.Function; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -55,6 +53,8 @@ import com.google.errorprone.annotations.CompileTimeConstant; import com.google.errorprone.annotations.MustBeClosed; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import uk.ac.manchester.spinnaker.alloc.SpallocProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.StateControlProperties; import uk.ac.manchester.spinnaker.alloc.allocator.Epochs; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java index 2a94f04d36..3afc045077 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java @@ -20,8 +20,6 @@ import static org.slf4j.LoggerFactory.getLogger; import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT; -import javax.annotation.PostConstruct; - import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Role; @@ -30,6 +28,7 @@ import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Component; +import jakarta.annotation.PostConstruct; import uk.ac.manchester.spinnaker.alloc.SpallocProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.ReportProperties; 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 c631b1d081..2c8d82373e 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 @@ -23,12 +23,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/bmp/BMPController.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BMPController.java index 5b85123555..c09a002d45 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 @@ -56,9 +56,6 @@ import java.util.function.Consumer; import java.util.function.Function; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - import org.slf4j.Logger; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanInitializationException; @@ -74,6 +71,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.AllocatorProperties; 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 d8c8af5aeb..fe0b7dd205 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 @@ -52,14 +52,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; 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 c34bdca557..50f47fe8fc 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 @@ -18,8 +18,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; @@ -27,13 +27,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 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 f50ba934ac..00bfaf0ade 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 @@ -27,13 +27,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; 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 e48275a484..715c162a7d 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 @@ -28,9 +28,6 @@ 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; @@ -38,6 +35,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; 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 cb5d6d773e..752db6bbf1 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 @@ -37,9 +37,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; @@ -49,6 +46,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper; 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; 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 c5986ba183..2cbb8c1cc0 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 @@ -42,13 +42,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.ServiceVersion; import uk.ac.manchester.spinnaker.alloc.SpallocProperties; import uk.ac.manchester.spinnaker.alloc.allocator.Epochs; 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 31e98e972f..1534c95e81 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 @@ -16,21 +16,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/DatabaseCache.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java index be6a5bc90a..ca09aa5854 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java @@ -28,11 +28,11 @@ import java.util.ArrayList; import java.util.List; -import javax.annotation.PreDestroy; - import org.slf4j.Logger; import org.springframework.dao.DataAccessResourceFailureException; +import jakarta.annotation.PreDestroy; + /** * A thread-aware cache of database connections. This looks after ensuring that * connections are closed when their thread is no longer running; ideal for diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java index 4c43842aae..2a4b5136d2 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java @@ -83,9 +83,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - import org.apache.commons.io.IOUtils; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.slf4j.Logger; @@ -108,6 +105,8 @@ import com.google.errorprone.annotations.MustBeClosed; import com.google.errorprone.annotations.concurrent.GuardedBy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import uk.ac.manchester.spinnaker.alloc.SpallocProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.DBProperties; import uk.ac.manchester.spinnaker.storage.ResultColumn; 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 b35c014076..d689d2b7f4 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 @@ -16,20 +16,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/proxy/SpinWSHandler.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/SpinWSHandler.java index a82f587b26..40f21341ad 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 @@ -16,11 +16,11 @@ */ 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.Objects.requireNonNull; 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; @@ -33,9 +33,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; @@ -50,6 +47,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 c7fbe925ad..4d83ef65b6 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 @@ -16,19 +16,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; @@ -38,6 +31,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; /** 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 487ab02d40..46b03b04d8 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 @@ -16,22 +16,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 2b34d9ac43..4a82419ce3 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 @@ -43,7 +43,7 @@ import java.util.Optional; import java.util.regex.Pattern; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; 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 08c36f2091..9959528adf 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 @@ -24,10 +24,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; @@ -37,6 +33,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 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 80721ee54c..69f6a71788 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 @@ -21,12 +21,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 1f133305fc..9fc35b6ded 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 @@ -56,7 +56,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 = isAdmin(authorities); 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 3f252cfe92..37663a9b15 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 @@ -38,7 +38,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.AbstractAuthenticationToken; 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.authority.mapping.GrantedAuthoritiesMapper; @@ -70,7 +70,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); @@ -184,13 +184,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/*")) 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 c69929bc26..ee3542dacb 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 @@ -20,12 +20,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/CreateJobResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobResponse.java index 263b43fc03..784eb1848d 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 @@ -20,11 +20,10 @@ 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; /** 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 f45c0ee71c..4566638e96 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 @@ -28,13 +28,12 @@ import java.time.Instant; import java.util.Optional; -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 f0531e7fab..8ad78accfb 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 @@ -23,10 +23,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/MachineResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachineResponse.java index e56d011adf..59a80959c7 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 @@ -26,10 +26,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 acf50570fe..bcc6c53b08 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 @@ -24,8 +24,7 @@ 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; 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 a4b5eaa409..918591bc00 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 @@ -16,27 +16,27 @@ */ 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 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. 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 7cdfb7abb8..6e3e135b0a 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 @@ -23,13 +23,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 b9739f6227..4451f0206d 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 @@ -17,8 +17,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; @@ -42,28 +42,11 @@ 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; @@ -76,6 +59,23 @@ 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.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 67b16cff03..0d764dc748 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 @@ -16,19 +16,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; @@ -38,6 +34,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; 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 ee0e26a985..548fe85b30 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 @@ -22,11 +22,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.ArrayList; import java.util.HashMap; -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; 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 9329256088..88ce5a09e2 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 @@ -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.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 99c23b61f0..6a053b0298 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,8 +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; @@ -33,6 +31,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; 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 1b1c119152..8b2f882590 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 @@ -29,8 +29,6 @@ import java.security.Principal; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import org.slf4j.Logger; @@ -50,6 +48,8 @@ import com.google.errorprone.annotations.Keep; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; 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 1202f7f87f..a584f1c16c 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 @@ -23,10 +23,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/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 ea3a6edf42..e0ef23c4ef 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 @@ -18,9 +18,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; @@ -32,9 +30,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; @@ -44,6 +39,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; +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; 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 b8721ce1b3..0f4562ccc1 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 @@ -19,10 +19,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 From f160cd156d7c8a864a0ab312ce577a7d54a22bc4 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 11:46:41 +0000 Subject: [PATCH 005/194] Update Java version to 17 This is the start of a migration process where we adopt new language and library features. We're not stopping off at 14 on the way because Spring and Jakarta are going to force the larger stride. --- pom.xml | 42 +++--------------------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/pom.xml b/pom.xml index 656d95c7be..2b6141c6b8 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ along with this program. If not, see . UTF-8 - 11 + 17 true true @@ -471,10 +471,8 @@ along with this program. If not, see . https://docs.spring.io/spring-framework/docs/current/javadoc-api/ https://docs.spring.io/spring-security/site/docs/current/api/ https://docs.spring.io/spring-boot/docs/current/api/ - https://jakarta.ee/specifications/servlet/4.0/apidocs/ + https://cxf.apache.org/javadoc/latest-3.0.x/ https://errorprone.info/api/latest/ https://fasterxml.github.io/jackson-core/javadoc/${jackson.doc.version}/ https://fasterxml.github.io/jackson-databind/javadoc/${jackson.doc.version}/ @@ -739,6 +737,7 @@ along with this program. If not, see . SpiNNaker-front-end SpiNNaker-allocserv SpiNNaker-py2json + keycloak-management-client SpiNNaker Java Host Implementation of the host software for SpiNNaker in Java. @@ -954,13 +953,6 @@ along with this program. If not, see . - - - KeycloakClient - - keycloak-management-client - - CheckForFIXME @@ -998,34 +990,6 @@ along with this program. If not, see . - - Java17extras - - [17,) - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - - https://docs.spring.io/spring-framework/docs/current/javadoc-api/ - https://docs.spring.io/spring-security/site/docs/current/api/ - https://docs.spring.io/spring-boot/docs/current/api/ - https://jakarta.ee/specifications/servlet/4.0/apidocs/ - https://cxf.apache.org/javadoc/latest-3.0.x/ - https://errorprone.info/api/latest/ - https://fasterxml.github.io/jackson-core/javadoc/${jackson.doc.version}/ - https://fasterxml.github.io/jackson-databind/javadoc/${jackson.doc.version}/ - https://www.slf4j.org/api/ - - - - - - ErrorProne From 17649e508730f78371480eb4852384751787bc4f Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 11:50:24 +0000 Subject: [PATCH 006/194] Update Java versions in workflows --- .github/workflows/build.yml | 14 +++++++------- .github/workflows/publish-pkgs.yml | 2 +- .github/workflows/publish.yml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0278a5eb2a..4cad10edc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: # Minimum Java version! - java: [11] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [11, 14, 17] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK @@ -78,8 +78,8 @@ jobs: CI_BUILD_URL: https://github.com/${{ github.repository }}/commit/${{ github.event.after }}/checks COVERALLS_SECRET: ${{ secrets.GITHUB_TOKEN }} continue-on-error: true - - name: Upload Build (JDK 11 only) - if: matrix.java == 11 + - name: Upload Build (JDK 17 only) + if: matrix.java == 17 uses: actions/upload-artifact@v3 with: name: spinnaker-exe.jar @@ -91,7 +91,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [11, 14] + java: [17] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} @@ -113,11 +113,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3.6.0 with: distribution: 'zulu' - java-version: 11 + java-version: 17 cache: 'maven' - name: "Check: No FIXMEs left" diff --git a/.github/workflows/publish-pkgs.yml b/.github/workflows/publish-pkgs.yml index 3cb9c63bc8..efd41cb300 100644 --- a/.github/workflows/publish-pkgs.yml +++ b/.github/workflows/publish-pkgs.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-java@v3.6.0 with: - java-version: '11' + java-version: '17' distribution: 'zulu' - name: Publish package run: mvn --batch-mode deploy diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 36ba7ced35..0db9223d5a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [14] + java: [17] env: SETTINGS_FILE: .github/settings.xml SITE_DIR: target/staging From 0a9ba66a23447db9e8b5706c5c5c5d6cba43bae3 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 12:00:59 +0000 Subject: [PATCH 007/194] CodeQL workflow was defaulting to Java 11... --- .github/workflows/codeql-analysis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6bf77681aa..94750e1c73 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -62,6 +62,12 @@ jobs: # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Set up right Java version: https://github.com/github/codeql-action/issues/825 + - uses: actions/setup-java@v1 + with: + java-version: 17 + distribution: zulu + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild From eeb2664fd971075008dfebdb00ecc3f4f69ec773 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 12:03:01 +0000 Subject: [PATCH 008/194] Update version of setup-java too --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 94750e1c73..61787a2514 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -63,7 +63,7 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main # Set up right Java version: https://github.com/github/codeql-action/issues/825 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v3.6.0 with: java-version: 17 distribution: zulu From 24cebe0b8ad27c6690b44cc6f7b67aa381ce1524 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 12:16:42 +0000 Subject: [PATCH 009/194] Remove Java version override --- keycloak-management-client/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/keycloak-management-client/pom.xml b/keycloak-management-client/pom.xml index c721c871ee..4a8a48f743 100644 --- a/keycloak-management-client/pom.xml +++ b/keycloak-management-client/pom.xml @@ -32,10 +32,6 @@ along with this program. If not, see . SpiNNaker-allocserv. You probably don't need to ever use this code! - - 11 - - com.fasterxml.jackson.core From e4889753255fdbbfec6fee6dfadede28b884fd53 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 28 Nov 2022 15:46:02 +0000 Subject: [PATCH 010/194] Multiline string constants! I have been wanting this for a long long time... --- .../spinnaker/alloc/db/SQLQueries.java | 1597 ++++++++++------- .../spinnaker/alloc/SupportQueries.java | 134 +- .../spinnaker/alloc/TestSupport.java | 25 +- .../alloc/allocator/AllocatorTest.java | 9 +- .../alloc/allocator/FirmwareLoaderTest.java | 7 +- .../spinnaker/alloc/compat/JsonTest.java | 105 +- .../spinnaker/alloc/compat/V1CompatTest.java | 2 + .../alloc/security/LocalAuthTest.java | 17 +- .../spinnaker/alloc/web/JsonTest.java | 99 +- .../spinnaker/messages/model/Version.java | 14 +- .../spinnaker/messages/model/VersionInfo.java | 10 +- .../front_end/iobuf/TestIobufRequest.java | 24 +- .../machine/bean/TestChipDetails.java | 10 +- .../spinnaker/machine/bean/TestChipbean.java | 13 +- .../spinnaker/machine/tags/TestIPTag.java | 16 +- .../spinnaker/storage/sqlite/SQL.java | 171 +- .../spinnaker/tools/CredentialDB.java | 44 +- 17 files changed, 1416 insertions(+), 881 deletions(-) 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 ac10a70967..b43c8dd05d 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 @@ -61,20 +61,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") @@ -85,10 +87,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") @@ -99,10 +104,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 + """; /** Count things on a machine. */ @Parameter("machine_id") @@ -110,16 +118,18 @@ public abstract class SQLQueries { @ResultColumn("in_use") @ResultColumn("num_jobs") @SingleRowResult - protected static final String COUNT_MACHINE_THINGS = - "WITH args(m) AS (VALUES (: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 (VALUES (: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") @@ -128,10 +138,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") @@ -140,10 +152,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") @@ -164,40 +179,47 @@ 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 (that is queued or ready). */ @Parameter("job_id") @ResultColumn("board_id") - protected static final String GET_JOB_BOARDS = - "SELECT board_id FROM boards JOIN jobs " - + "ON boards.allocated_job = jobs.job_id " - + "WHERE boards.allocated_job = :job_id " - // job is QUEUED or READY - + "AND (jobs.job_state IN (1, 3))"; + protected static final String GET_JOB_BOARDS = """ + SELECT board_id + FROM boards + JOIN jobs ON boards.allocated_job = jobs.job_id + WHERE boards.allocated_job = :job_id + AND (jobs.job_state IN (1, 3)) -- job is QUEUED or READY + """; /** Gets information about live jobs. */ @ResultColumn("job_id") @@ -208,30 +230,37 @@ public abstract class SQLQueries { @ResultColumn("allocation_size") @ResultColumn("keepalive_host") @ResultColumn("user_name") - 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 " - + "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 + 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") @@ -240,13 +269,16 @@ 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, CAST(strftime('%s','now') AS INTEGER), " - + "CAST(strftime('%s','now') AS INTEGER), " + /* 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, CAST(strftime('%s','now') AS INTEGER), + CAST(strftime('%s','now') AS INTEGER), + 1) -- job starts QUEUED + """; /** Create a request to allocate a number of boards. */ @Parameter("job_id") @@ -254,11 +286,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") @@ -267,20 +299,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") @@ -290,24 +324,30 @@ 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") @@ -315,27 +355,38 @@ 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 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. @@ -344,13 +395,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. @@ -364,12 +418,16 @@ public abstract class SQLQueries { @ResultColumn("frame") @ResultColumn("board_num") @ResultColumn("address") - protected static final String GET_LIVE_BOARDS = - "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, " - + "boards.address FROM boards JOIN bmp USING (bmp_id) " - + "WHERE boards.machine_id = :machine_id " - + "AND board_num IS NOT NULL " - + "AND functioning IS 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 + FROM boards + JOIN bmp USING (bmp_id) + WHERE boards.machine_id = :machine_id + AND board_num IS NOT NULL + AND functioning IS 1 + ORDER BY z ASC, x ASC, y ASC + """; /** * Get the boards (and related info) of a machine that have been disabled. @@ -383,12 +441,15 @@ public abstract class SQLQueries { @ResultColumn("frame") @ResultColumn("board_num") @ResultColumn("address") - protected static final String GET_DEAD_BOARDS = - "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, " - + "boards.address FROM boards JOIN bmp USING (bmp_id) " - + "WHERE boards.machine_id = :machine_id " - + "AND (board_num IS NULL OR functioning IS 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 + FROM boards + JOIN bmp USING (bmp_id) + WHERE boards.machine_id = :machine_id + AND (board_num IS NULL OR functioning IS 0) + ORDER BY z ASC, x ASC, y ASC + """; /** * Get all the boards (and related info) of a machine. @@ -404,12 +465,14 @@ public abstract class SQLQueries { @ResultColumn("frame") @ResultColumn("board_num") @ResultColumn("address") - protected static final String GET_ALL_BOARDS = - "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, " - + "boards.address 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 + 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. @@ -424,11 +487,14 @@ public abstract class SQLQueries { @ResultColumn("frame") @ResultColumn("board_num") @ResultColumn("address") - protected static final String GET_ALL_BOARDS_OF_ALL_MACHINES = - "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, " - + "boards.address 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 + 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. @@ -442,30 +508,36 @@ public abstract class SQLQueries { @ResultColumn("frame") @ResultColumn("board_num") @ResultColumn("address") - protected static final String GET_JOB_BOARD_COORDS = - "SELECT board_id, x, y, z, bmp.cabinet, bmp.frame, board_num, " - + "boards.address 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 + 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 @@ -475,25 +547,30 @@ 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 = " - + "CAST(strftime('%s','now') AS INTEGER), " - + "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 = CAST(strftime('%s','now') AS INTEGER), + 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 - + "WHERE job_id = :job_id AND job_state != 4"; + protected static final String DESTROY_JOB = """ + UPDATE jobs + SET job_state = 4, death_reason = :death_reason + WHERE job_id = :job_id AND job_state != 4 -- job is not DESTROYED + """; /** * Get the number of boards that are allocated to a job that are switched @@ -502,9 +579,11 @@ public abstract class SQLQueries { @Parameter("job_id") @ResultColumn("total_on") @SingleRowResult - protected static final String GET_SUM_BOARDS_POWERED = - "SELECT sum(board_power) AS total_on FROM boards " - + "WHERE allocated_job = :job_id"; + protected static final String GET_SUM_BOARDS_POWERED = """ + SELECT sum(board_power) AS total_on + FROM boards + WHERE allocated_job = :job_id + """; /** Get connection info for board allocated to a job. */ @Parameter("job_id") @@ -515,13 +594,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") @@ -531,9 +611,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") @@ -541,17 +624,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. @@ -564,12 +653,15 @@ public abstract class SQLQueries { @ResultColumn("reported_issue") @ResultColumn("reporter_name") @ResultColumn("report_timestamp") - 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 GROUP BY board_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 + GROUP BY board_id + """; /** * Get the problem reports about a board. @@ -582,16 +674,20 @@ public abstract class SQLQueries { @ResultColumn("reported_issue") @ResultColumn("reporter_name") @ResultColumn("report_timestamp") - 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") @@ -599,10 +695,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. @@ -616,22 +715,28 @@ public abstract class SQLQueries { @Parameter("board_id") @Parameter("num_boards") @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 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 + 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. @@ -640,9 +745,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. @@ -650,9 +757,11 @@ public abstract class SQLQueries { * @see BMPController */ @Parameter("job_id") - protected static final String DEALLOCATE_BOARDS_JOB = - "UPDATE boards SET allocated_job = NULL " - + "WHERE allocated_job = :job_id"; + protected static final String DEALLOCATE_BOARDS_JOB = """ + UPDATE boards + SET allocated_job = NULL + WHERE allocated_job = :job_id + """; /** * Set the power state of a board. Related timestamps are updated by @@ -660,9 +769,11 @@ public abstract class SQLQueries { */ @Parameter("board_power") @Parameter("board_id") - protected static final String SET_BOARD_POWER = - "UPDATE boards SET board_power = :board_power " - + "WHERE board_id = :board_id"; + protected static final String SET_BOARD_POWER = """ + UPDATE boards + SET board_power = :board_power + WHERE board_id = :board_id + """; /** * Find jobs that have expired their keepalive interval. @@ -670,11 +781,13 @@ 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 < " - + "CAST(strftime('%s','now') AS INTEGER)"; + 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 < + CAST(strftime('%s','now') AS INTEGER) + """; /** * Set the state and number of pending changes for a job. @@ -684,27 +797,35 @@ 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 + """; /** 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 boards allocated to a job. */ @Parameter("job_id") - protected static final String KILL_JOB_PENDING = - "DELETE FROM pending_changes WHERE job_id = :job_id"; + protected static final String KILL_JOB_PENDING = """ + DELETE FROM pending_changes + 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. @@ -716,8 +837,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 how many requests to change the power state of a board are currently @@ -725,8 +848,10 @@ public abstract class SQLQueries { */ @ResultColumn("c") @SingleRowResult - protected static final String COUNT_PENDING_CHANGES = - "SELECT count(*) AS c FROM pending_changes"; + protected static final String COUNT_PENDING_CHANGES = """ + SELECT count(*) AS c + FROM pending_changes + """; /** * Get the requests (not already being processed) to change the power of a @@ -750,14 +875,16 @@ public abstract class SQLQueries { @ResultColumn("bmp_id") @ResultColumn("cabinet") @ResultColumn("frame") - 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, " - + "in_progress, from_state, to_state, board_num, " - + "boards.bmp_id, cabinet, frame " - + "FROM pending_changes JOIN boards USING (board_id) " - + "JOIN bmp USING (bmp_id) " - + "WHERE job_id = :job_id AND NOT in_progress"; + 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, + in_progress, from_state, to_state, board_num, + boards.bmp_id, cabinet, frame + FROM pending_changes + JOIN boards USING (board_id) + JOIN bmp USING (bmp_id) + WHERE job_id = :job_id AND NOT in_progress + """; /** * Set the progress status of a request to change the power state of a @@ -765,9 +892,11 @@ public abstract class SQLQueries { */ @Parameter("in_progress") @Parameter("change_id") - protected static final String SET_IN_PROGRESS = - "UPDATE pending_changes SET in_progress = :in_progress " - + "WHERE change_id = :change_id"; + protected static final String SET_IN_PROGRESS = """ + UPDATE pending_changes + SET in_progress = :in_progress + WHERE change_id = :change_id + """; /** * Insert a BMP. @@ -779,9 +908,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. @@ -799,11 +930,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. @@ -816,9 +950,11 @@ public abstract class SQLQueries { @Parameter("dir_2") @Parameter("live") @GeneratesID - protected static final String INSERT_LINK = - "INSERT OR 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 OR 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. @@ -830,10 +966,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. @@ -844,8 +981,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. @@ -853,8 +993,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. @@ -863,9 +1005,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 @@ -876,9 +1020,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") @@ -894,15 +1040,18 @@ public abstract class SQLQueries { @ResultColumn("bmp_serial_id") @ResultColumn("physical_serial_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 " - + "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 + 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") @@ -921,16 +1070,19 @@ public abstract class SQLQueries { @ResultColumn("bmp_serial_id") @ResultColumn("physical_serial_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 " - + "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 + 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") @@ -949,18 +1101,21 @@ public abstract class SQLQueries { @ResultColumn("bmp_serial_id") @ResultColumn("physical_serial_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 " - + "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 + 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") @@ -977,17 +1132,20 @@ public abstract class SQLQueries { @ResultColumn("bmp_serial_id") @ResultColumn("physical_serial_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 " - + "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 + 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. @@ -997,9 +1155,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 @@ -1009,9 +1170,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. @@ -1022,11 +1185,14 @@ public abstract class SQLQueries { @ResultColumn("quota_total") @ResultColumn("user_id") @SingleRowResult - protected static final String GET_USER_QUOTA = "SELECT * FROM (" - + "SELECT SUM(quota) AS quota_total, quotas.user_id FROM quotas " - + "JOIN user_info USING (user_id) " - + "WHERE user_info.user_name = :user_name" - + ") WHERE user_id IS NOT NULL"; + protected static final String GET_USER_QUOTA = """ + SELECT * FROM ( + SELECT SUM(quota) AS quota_total, quotas.user_id + FROM quotas + JOIN user_info USING (user_id) + WHERE user_info.user_name = :user_name) + WHERE user_id IS NOT NULL + """; /** * Get the quota for a group. @@ -1036,8 +1202,12 @@ public abstract class SQLQueries { @Parameter("group_id") @ResultColumn("quota") @SingleRowResult - protected static final String GET_GROUP_QUOTA = - "SELECT quota FROM groups WHERE group_id = :group_id LIMIT 1"; + protected static final String GET_GROUP_QUOTA = """ + SELECT quota + FROM groups + WHERE group_id = :group_id + LIMIT 1 + """; /** * Get the current non-consolidated usage for a group. @@ -1047,9 +1217,11 @@ public abstract class SQLQueries { @Parameter("group_id") @ResultColumn("current_usage") @SingleRowResult - protected static final String GET_CURRENT_USAGE = - "SELECT SUM(usage) AS current_usage FROM jobs_usage " - + "WHERE group_id = :group_id"; + protected static final String GET_CURRENT_USAGE = """ + SELECT SUM(usage) AS current_usage + FROM jobs_usage + WHERE group_id = :group_id + """; /** * Get usage of a job and the quota against which that applies. @@ -1060,10 +1232,12 @@ public abstract class SQLQueries { @ResultColumn("usage") @ResultColumn("quota") @SingleRowResult - protected static final String GET_JOB_USAGE_AND_QUOTA = - "SELECT [usage], quota FROM jobs_usage " - + "WHERE :job_id = :job_id AND [usage] IS NOT NULL " - + "AND quota IS NOT NULL LIMIT 1"; + protected static final String GET_JOB_USAGE_AND_QUOTA = """ + SELECT [usage], quota FROM jobs_usage + WHERE :job_id = :job_id + AND [usage] IS NOT NULL AND quota IS NOT NULL + LIMIT 1 + """; /** * Get resource usage info about completed jobs that have yet to be @@ -1074,9 +1248,11 @@ public abstract class SQLQueries { @ResultColumn("job_id") @ResultColumn("group_id") @ResultColumn("usage") - protected static final String GET_CONSOLIDATION_TARGETS = - "SELECT job_id, group_id, [usage] FROM jobs_usage " - + "WHERE complete AND quota IS NOT NULL"; + protected static final String GET_CONSOLIDATION_TARGETS = """ + SELECT job_id, group_id, [usage] + FROM jobs_usage + WHERE complete AND quota IS NOT NULL + """; /** * Reduce a group's quota on a machine by a specified amount. @@ -1085,9 +1261,11 @@ public abstract class SQLQueries { */ @Parameter("usage") @Parameter("group_id") - protected static final String DECREMENT_QUOTA = - "UPDATE groups SET quota = quota - :usage " - + "WHERE group_id = :group_id AND quota IS NOT NULL"; + protected static final String DECREMENT_QUOTA = """ + UPDATE 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. @@ -1095,8 +1273,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 @@ -1108,10 +1289,12 @@ public abstract class SQLQueries { @Parameter("group_id") @ResultColumn("group_name") @ResultColumn("quota") - protected static final String ADJUST_QUOTA = - "UPDATE groups SET quota = max(0, quota + :delta) " - + "WHERE group_id = :group_id AND quota IS NOT NULL " - + "RETURNING group_name, quota"; + protected static final String ADJUST_QUOTA = """ + UPDATE groups + SET quota = max(0, quota + :delta) + WHERE group_id = :group_id AND quota IS NOT NULL + RETURNING group_name, quota + """; /** * Get details about a user. This is pretty much everything except their @@ -1131,13 +1314,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 @@ -1157,13 +1343,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 @@ -1183,14 +1372,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. @@ -1202,9 +1393,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 @@ -1216,12 +1410,14 @@ public abstract class SQLQueries { @Parameter("group_name") @ResultColumn("group_id") @SingleRowResult - protected static final String GET_GROUP_BY_NAME_AND_MEMBER = - "SELECT groups.group_id FROM 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 groups.group_id + FROM 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. @@ -1231,13 +1427,14 @@ public abstract class SQLQueries { @Parameter("user_name") @ResultColumn("group_id") @ResultColumn("quota") - protected static final String GET_GROUPS_AND_QUOTAS_OF_USER = - "SELECT groups.group_id, COALESCE(groups.quota, 1) AS quota " - + "FROM group_memberships " - + "JOIN user_info USING (user_id) " - + "JOIN groups USING (group_id) " - + "WHERE user_name = :user_name AND quota > 0 " - + "ORDER BY groups.quota DESC"; + protected static final String GET_GROUPS_AND_QUOTAS_OF_USER = """ + SELECT groups.group_id, COALESCE(groups.quota, 1) AS quota + FROM group_memberships + JOIN user_info USING (user_id) + JOIN groups USING (group_id) + WHERE user_name = :user_name AND quota > 0 + ORDER BY groups.quota DESC + """; /** * List the members of a group. @@ -1250,12 +1447,14 @@ public abstract class SQLQueries { @ResultColumn("group_name") @ResultColumn("user_id") @ResultColumn("user_name") - protected static final String GET_USERS_OF_GROUP = - "SELECT membership_id, groups.group_id, groups.group_name, " - + "user_info.user_id, user_info.user_name " - + "FROM group_memberships JOIN user_info USING (user_id) " - + "JOIN groups USING (group_id) " - + "WHERE group_id = :group_id"; + protected static final String GET_USERS_OF_GROUP = """ + SELECT membership_id, groups.group_id, groups.group_name, + user_info.user_id, user_info.user_name + FROM group_memberships + JOIN user_info USING (user_id) + JOIN groups USING (group_id) + WHERE group_id = :group_id + """; /** * Get the details from a specific membership. @@ -1269,12 +1468,15 @@ public abstract class SQLQueries { @ResultColumn("user_name") @ResultColumn("group_name") @SingleRowResult - protected static final String GET_MEMBERSHIP = - "SELECT membership_id, user_info.user_id, groups.group_id, " - + "user_name, group_name FROM group_memberships " - + "JOIN user_info USING (user_id) " - + "JOIN groups USING (group_id) " - + "WHERE membership_id = :membership_id"; + protected static final String GET_MEMBERSHIP = """ + SELECT membership_id, user_info.user_id, groups.group_id, + user_name, group_name + FROM group_memberships + JOIN user_info USING (user_id) + JOIN groups USING (group_id) + WHERE membership_id = :membership_id + LIMIT 1 + """; /** * Get the memberships of a user. @@ -1287,12 +1489,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, groups.group_id, " - + "user_name, group_name FROM group_memberships " - + "JOIN user_info USING (user_id) " - + "JOIN 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, groups.group_id, + user_name, group_name + FROM group_memberships + JOIN user_info USING (user_id) + JOIN groups USING (group_id) + WHERE group_memberships.user_id = :user_id + """; /** * Create a group record. @@ -1303,9 +1507,11 @@ public abstract class SQLQueries { @Parameter("quota") @Parameter("group_type") @GeneratesID - protected static final String CREATE_GROUP = - "INSERT INTO groups(group_name, quota, group_type) " - + "VALUES(:group_name, :quota, :group_type)"; + protected static final String CREATE_GROUP = """ + INSERT INTO groups( + group_name, quota, group_type) + VALUES (:group_name, :quota, :group_type) + """; /** * Create a group record. @@ -1315,9 +1521,11 @@ public abstract class SQLQueries { @Parameter("group_name") @Parameter("quota") @Parameter("group_type") - protected static final String CREATE_GROUP_IF_NOT_EXISTS = - "INSERT OR IGNORE INTO groups(group_name, quota, group_type) " - + "VALUES(:group_name, :quota, :group_type)"; + protected static final String CREATE_GROUP_IF_NOT_EXISTS = """ + INSERT OR IGNORE INTO 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. @@ -1327,10 +1535,11 @@ public abstract class SQLQueries { @Parameter("group_id") @ResultColumn("group_name") @SingleRowResult - protected static final String DELETE_GROUP = - "DELETE FROM groups WHERE group_id = :group_id " - // + "LIMIT 1 " // Not supported in Xerial driver build - + "RETURNING group_name"; + protected static final String DELETE_GROUP = """ + DELETE FROM groups WHERE group_id = :group_id + -- LIMIT 1 -- Not supported in Xerial driver build + RETURNING group_name + """; /** * Update a single group record's name and quota. @@ -1345,11 +1554,13 @@ public abstract class SQLQueries { @ResultColumn("quota") @ResultColumn("group_type") @SingleRowResult - protected static final String UPDATE_GROUP = "UPDATE groups SET " - + "group_name = COALESCE(:group_name, group_name), " - + "quota = :quota WHERE group_id = :group_id " - // + "LIMIT 1 " // Not supported in Xerial driver build - + "RETURNING group_id, group_name, quota, group_type"; + protected static final String UPDATE_GROUP = """ + UPDATE groups + SET group_name = COALESCE(:group_name, group_name), + quota = :quota WHERE group_id = :group_id + -- LIMIT 1 -- Not supported in Xerial driver build + RETURNING group_id, group_name, quota, group_type + """; /** * Adds a user to a group. @@ -1359,9 +1570,11 @@ 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)"; + protected static final String ADD_USER_TO_GROUP = """ + INSERT INTO group_memberships( + user_id, group_id) + VALUES (:user_id, :group_id) + """; /** * Removes a user from a group. @@ -1370,9 +1583,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 @@ -1380,8 +1594,10 @@ public abstract class SQLQueries { * * @see LocalAuthProviderImpl */ - protected static final String GROUP_SYNC_MAKE_TEMP_TABLE = - "CREATE TEMP TABLE IF NOT EXISTS usergroupids(group_id INTEGER)"; + protected static final String GROUP_SYNC_MAKE_TEMP_TABLE = """ + CREATE TEMP TABLE IF NOT EXISTS usergroupids( + group_id INTEGER) + """; /** * Step 2 of group synchronisation: add a desired group to the temp table. @@ -1393,10 +1609,12 @@ public abstract class SQLQueries { */ @Parameter("group_name") @Parameter("group_type") - protected static final String GROUP_SYNC_INSERT_TEMP_ROW = - "INSERT INTO temp.usergroupids SELECT group_id FROM groups " - + "WHERE group_name = :group_name " - + "AND group_type = :group_type"; + protected static final String GROUP_SYNC_INSERT_TEMP_ROW = """ + INSERT INTO temp.usergroupids + SELECT group_id FROM groups + WHERE group_name = :group_name + AND group_type = :group_type + """; /** * Step 3 of group synchronisation: add real missing groups. Requires the @@ -1408,10 +1626,12 @@ public abstract class SQLQueries { * @see LocalAuthProviderImpl */ @Parameter("user_id") - protected static final String GROUP_SYNC_ADD_GROUPS = - "INSERT OR IGNORE INTO group_memberships(user_id, group_id) " - + "SELECT :user_id AS user_id, " - + "group_id FROM temp.usergroupids"; + protected static final String GROUP_SYNC_ADD_GROUPS = """ + INSERT OR IGNORE INTO group_memberships( + user_id, group_id) + SELECT :user_id AS user_id, group_id + FROM temp.usergroupids + """; /** * Step 4 of group synchronisation: remove real groups no longer wanted. @@ -1423,10 +1643,11 @@ 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 temp.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 temp.usergroupids) + """; /** * Step 5 of group synchronisation: drop the temporary table. Except we @@ -1438,8 +1659,9 @@ public abstract class SQLQueries { * * @see LocalAuthProviderImpl */ - protected static final String GROUP_SYNC_DROP_TEMP_TABLE = - "DELETE FROM temp.usergroupids"; + protected static final String GROUP_SYNC_DROP_TEMP_TABLE = """ + DELETE FROM temp.usergroupids + """; /** * Test if a user account is locked or disabled. @@ -1451,9 +1673,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. @@ -1465,9 +1690,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. @@ -1476,11 +1704,13 @@ 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 = " - + "CAST(strftime('%s','now') AS INTEGER), " - + "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 = + CAST(strftime('%s','now') AS INTEGER), + failure_count = 0, openid_subject = :openid_subject + WHERE user_id = :user_id + """; /** * Note the login failure. @@ -1491,12 +1721,14 @@ public abstract class SQLQueries { @Parameter("user_id") @ResultColumn("locked") @SingleRowResult - protected static final String MARK_LOGIN_FAILURE = - "UPDATE user_info SET failure_count = failure_count + 1, " - + "last_fail_timestamp = " - + "CAST(strftime('%s','now') AS INTEGER), " - + "locked = (failure_count + 1 >= :failure_limit) " - + "WHERE user_id = :user_id RETURNING locked"; + protected static final String MARK_LOGIN_FAILURE = """ + UPDATE user_info + SET failure_count = failure_count + 1, + last_fail_timestamp = CAST(strftime('%s','now') AS INTEGER), + locked = (failure_count + 1 >= :failure_limit) + WHERE user_id = :user_id + RETURNING locked + """; /** * Unlock accounts. @@ -1505,11 +1737,14 @@ public abstract class SQLQueries { */ @Parameter("lock_interval") @ResultColumn("user_name") - 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 " - + "< CAST(strftime('%s','now') AS INTEGER) " - + "AND locked RETURNING user_name"; + 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 < + CAST(strftime('%s','now') AS INTEGER) + AND locked + RETURNING user_name + """; /** * Delete a user. @@ -1517,8 +1752,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. @@ -1529,8 +1766,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. @@ -1539,9 +1780,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. @@ -1550,8 +1793,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. @@ -1560,9 +1806,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 @@ -1573,9 +1821,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. @@ -1584,9 +1834,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. @@ -1596,8 +1848,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. @@ -1608,9 +1862,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 @@ -1625,11 +1881,13 @@ public abstract class SQLQueries { @Parameter("disabled") @Parameter("openid_subject") @GeneratesID - protected static final String CREATE_USER = - "INSERT OR 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 OR 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. @@ -1640,8 +1898,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 groups"; + protected static final String LIST_ALL_GROUPS = """ + SELECT group_id, group_name, quota, group_type + FROM groups + """; /** * Get a list of all groups of a given type. @@ -1653,9 +1913,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 groups " - + "WHERE group_type = :type"; + protected static final String LIST_ALL_GROUPS_OF_TYPE = """ + SELECT group_id, group_name, quota, group_type + FROM groups + WHERE group_type = :type + """; /** * Get a group by it's ID. @@ -1668,9 +1930,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 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 groups + WHERE group_id = :group_id + LIMIT 1 + """; /** * Get a group by it's name. @@ -1683,9 +1948,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 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 groups + WHERE group_name = :group_name + LIMIT 1 + """; /** * Create a board issue report. @@ -1697,10 +1965,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) " - + "VALUES(:board_id, :job_id, :issue, :user_id)"; + protected static final String INSERT_BOARD_REPORT = """ + INSERT INTO board_reports( + board_id, job_id, reported_issue, reporter) + VALUES (:board_id, :job_id, :issue, :user_id) + """; /** * Actually delete a job record. Only called by the data tombstone-r. This @@ -1709,8 +1978,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 @@ -1720,15 +1991,19 @@ 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 + """; /** * Mark all pending changes as eligible for processing. Called once on * application startup when all internal queues are guaranteed to be empty. */ - protected static final String CLEAR_STUCK_PENDING = - "UPDATE pending_changes SET in_progress = 0"; + protected static final String CLEAR_STUCK_PENDING = """ + UPDATE pending_changes + SET in_progress = 0 + """; /** * Read the blacklisted chips for a board. @@ -1739,10 +2014,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. @@ -1754,11 +2031,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. @@ -1770,11 +2048,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. @@ -1782,10 +2061,11 @@ public abstract class SQLQueries { * @see MachineStateControl */ @Parameter("board_id") - protected static final String MARK_BOARD_BLACKLIST_CHANGED = - "UPDATE boards SET blacklist_set_timestamp = " - + "CAST(strftime('%s','now') AS INTEGER) " - + "WHERE board_id = :board_id"; + protected static final String MARK_BOARD_BLACKLIST_CHANGED = """ + UPDATE boards + SET blacklist_set_timestamp = CAST(strftime('%s','now') AS INTEGER) + WHERE board_id = :board_id + """; /** * Mark a board as having had its blacklist synchronised with the hardware. @@ -1793,10 +2073,12 @@ public abstract class SQLQueries { * @see MachineStateControl */ @Parameter("board_id") - protected static final String MARK_BOARD_BLACKLIST_SYNCHED = - "UPDATE boards SET blacklist_sync_timestamp = " - + "CAST(strftime('%s','now') AS INTEGER) " - + "WHERE board_id = :board_id"; + protected static final String MARK_BOARD_BLACKLIST_SYNCHED = """ + UPDATE boards + SET blacklist_sync_timestamp = + CAST(strftime('%s','now') AS INTEGER) + WHERE board_id = :board_id + """; /** * Asks whether the blacklist model for a board is believed to be @@ -1807,10 +2089,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 @@ -1822,15 +2107,19 @@ public abstract class SQLQueries { @Parameter("board_id") @Parameter("x") @Parameter("y") - protected static final String ADD_BLACKLISTED_CHIP = - "WITH args(board_id, x, y) AS (VALUES(:board_id, :x, :y))," - + "m(model) AS (SELECT board_model FROM machines " - + "JOIN boards USING (machine_id) " - + "JOIN args USING (board_id)) " - + "INSERT INTO blacklisted_chips(board_id, coord_id, notes)" - + "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 = """ + WITH args(board_id, x, y) AS (VALUES(:board_id, :x, :y))," + m(model) AS (SELECT board_model FROM machines + JOIN boards USING (machine_id) + JOIN args USING (board_id)) + INSERT INTO blacklisted_chips( + board_id, coord_id, notes) + 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 @@ -1843,16 +2132,19 @@ public abstract class SQLQueries { @Parameter("x") @Parameter("y") @Parameter("p") - protected static final String ADD_BLACKLISTED_CORE = - "WITH args(board_id, x, y, p) AS (VALUES(:board_id, :x, :y, :p))," - + "m(model) AS (SELECT board_model FROM machines " - + "JOIN boards USING (machine_id) " - + "JOIN args USING (board_id)) " - + "INSERT INTO blacklisted_cores(" - + "board_id, coord_id, physical_core, notes)" - + "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 = """ + WITH args(board_id, x, y, p) AS (VALUES(:board_id, :x, :y, :p)), + m(model) AS (SELECT board_model FROM machines + JOIN boards USING (machine_id) + JOIN args USING (board_id)) + INSERT INTO blacklisted_cores( + board_id, coord_id, physical_core, notes) + 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 @@ -1865,17 +2157,20 @@ public abstract class SQLQueries { @Parameter("x") @Parameter("y") @Parameter("direction") - protected static final String ADD_BLACKLISTED_LINK = - "WITH args(board_id, x, y, dir) AS (" - + "VALUES(:board_id, :x, :y, :direction))," - + "m(model) AS (SELECT board_model FROM machines " - + "JOIN boards USING (machine_id) " - + "JOIN args USING (board_id)) " - + "INSERT INTO blacklisted_links(" - + "board_id, coord_id, direction, notes)" - + "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 = """ + WITH args(board_id, x, y, dir) AS ( + VALUES(:board_id, :x, :y, :direction)), + m(model) AS (SELECT board_model FROM machines + JOIN boards USING (machine_id) + JOIN args USING (board_id)) + INSERT INTO blacklisted_links( + board_id, coord_id, direction, notes) + 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. @@ -1883,8 +2178,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. @@ -1892,8 +2189,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. @@ -1901,8 +2200,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. @@ -1916,13 +2217,16 @@ public abstract class SQLQueries { @ResultColumn("board_num") @ResultColumn("cabinet") @ResultColumn("frame") - protected static final String GET_BLACKLIST_WRITES = - "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, " - + "cabinet, frame, data 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.machine_id = :machine_id"; + protected static final String GET_BLACKLIST_WRITES = """ + SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, + cabinet, frame, data + 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.machine_id = :machine_id + """; /** * Get the list of reads (from the machine) of blacklist data to perform. @@ -1936,13 +2240,16 @@ public abstract class SQLQueries { @ResultColumn("board_num") @ResultColumn("cabinet") @ResultColumn("frame") - protected static final String GET_BLACKLIST_READS = - "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, " - + "cabinet, frame 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.machine_id = :machine_id"; + protected static final String GET_BLACKLIST_READS = """ + SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, + cabinet, frame + 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.machine_id = :machine_id + """; /** * Get the list of reads (from the machine) of serial data to perform. @@ -1956,13 +2263,16 @@ public abstract class SQLQueries { @ResultColumn("board_num") @ResultColumn("cabinet") @ResultColumn("frame") - protected static final String GET_SERIAL_INFO_REQS = - "SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, " - + "cabinet, frame 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.machine_id = :machine_id"; + protected static final String GET_SERIAL_INFO_REQS = """ + SELECT op_id, board_id, board_serial.bmp_serial_id, board_num, + cabinet, frame + 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.machine_id = :machine_id + """; /** * Set the BMP and physical serial IDs based on the information actually @@ -1975,13 +2285,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 CONFLICT DO UPDATE SET " - + "bmp_serial_id = excluded.bmp_serial_id, " - + "physical_serial_id = excluded.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 CONFLICT DO UPDATE + SET bmp_serial_id = excluded.bmp_serial_id, + physical_serial_id = excluded.physical_serial_id + """; /** * Mark a read of a blacklist as completed. @@ -1990,9 +2301,11 @@ public abstract class SQLQueries { */ @Parameter("data") @Parameter("op_id") - protected static final String COMPLETED_BLACKLIST_READ = - "UPDATE blacklist_ops SET data = :data, completed = 1 " - + "WHERE op_id = :op_id"; + protected static final String COMPLETED_BLACKLIST_READ = """ + UPDATE blacklist_ops + SET data = :data, completed = 1 + WHERE op_id = :op_id + """; /** * Mark a write of a blacklist as completed. @@ -2000,8 +2313,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 @@ -2010,8 +2326,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. @@ -2020,8 +2339,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 blacklist for a board. @@ -2034,11 +2356,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. @@ -2046,8 +2369,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. @@ -2056,9 +2381,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. @@ -2068,9 +2395,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. @@ -2079,9 +2408,11 @@ 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) + """; // SQL loaded from files because it is too complicated otherwise! 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 f5ee775b38..e03bfa9a9a 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 @@ -33,67 +33,95 @@ 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 + """; /** 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 machine_id = ? AND user_id = ?"; + String TEST_GET_QUOTA = """ + SELECT quota + FROM quotas + WHERE machine_id = ? AND user_id = ? + """; /** Set the quota for a group. */ @Parameter("quota") @Parameter("group") - String TEST_SET_QUOTA = - "UPDATE groups SET quota = :quota WHERE group_id = :group"; + String TEST_SET_QUOTA = """ + UPDATE groups + SET quota = :quota + WHERE group_id = :group + """; /** Create a machine, specifying the ID. */ @Parameter("machine_id") @@ -102,10 +130,11 @@ public interface SupportQueries { @Parameter("height") @Parameter("depth") @GeneratesID - String INSERT_MACHINE = - "INSERT OR IGNORE INTO machines(machine_id, machine_name, " - + "width, height, [depth], board_model) " - + "VALUES (?, ?, ?, ?, ?, 5)"; + String INSERT_MACHINE = """ + INSERT OR IGNORE INTO machines( + machine_id, machine_name, width, height, [depth], board_model) + VALUES (?, ?, ?, ?, ?, 5) + """; /** Create a BMP, specifying the ID. */ @Parameter("bmp_id") @@ -114,9 +143,11 @@ public interface SupportQueries { @Parameter("cabinet") @Parameter("frame") @GeneratesID - String INSERT_BMP_WITH_ID = - "INSERT OR IGNORE INTO bmp(bmp_id, machine_id, address, " - + "cabinet, frame) VALUES (?, ?, ?, ?, ?)"; + String INSERT_BMP_WITH_ID = """ + INSERT OR IGNORE INTO bmp( + bmp_id, machine_id, address, cabinet, frame) + VALUES (?, ?, ?, ?, ?) + """; /** Create a user, specifying the ID. */ @Parameter("user_id") @@ -124,26 +155,33 @@ public interface SupportQueries { @Parameter("trust_level") @Parameter("disabled") @GeneratesID - String INSERT_USER = "INSERT OR IGNORE INTO user_info(user_id, user_name, " - + "trust_level, disabled, encrypted_password) " - + "VALUES (?, ?, ?, ?, '*')"; + String INSERT_USER = """ + INSERT OR IGNORE 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 OR IGNORE INTO " - + "groups(group_id, group_name, quota, group_type) " - + "VALUES (?, ?, ?, 0)"; + String INSERT_GROUP = """ + INSERT OR IGNORE INTO 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 OR IGNORE INTO group_memberships(" - + "membership_id, user_id, group_id) VALUES (?, ?, ?)"; + String INSERT_MEMBER = """ + INSERT OR IGNORE INTO group_memberships( + membership_id, user_id, group_id) + VALUES (?, ?, ?) + """; /** Create a board, specifying the ID. */ @Parameter("board_id") @@ -158,11 +196,12 @@ public interface SupportQueries { @Parameter("root_y") @Parameter("board_power") @GeneratesID - String INSERT_BOARD_WITH_ID = - "INSERT OR IGNORE 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 OR IGNORE 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") @@ -177,10 +216,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 f1d4bc52fb..065b2906ba 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 @@ -261,8 +261,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); } } @@ -279,16 +282,21 @@ 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().map(string("reported_issue")).toList(); } }); @@ -401,7 +409,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/allocator/AllocatorTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/allocator/AllocatorTest.java index 65e8f9bd40..491827b870 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 @@ -391,9 +391,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(); }); } } 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 87f678102a..998e48a711 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 @@ -154,8 +154,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/compat/JsonTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/compat/JsonTest.java index c68b596418..4e238f790f 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 @@ -77,13 +77,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 @@ -96,14 +102,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 @@ -120,21 +128,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 @@ -142,11 +153,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 @@ -156,12 +174,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 7dcedd20db..e1e8c2cda2 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 @@ -59,6 +59,8 @@ "spalloc.compat.service-group=" + TestSupport.GROUP_NAME }) 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"; 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 a1e5a323f6..830e00e26c 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 @@ -72,10 +72,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); } }); @@ -85,8 +87,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(USER).map(Row.bool("locked")).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 ea3a6edf42..2d804532eb 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 @@ -226,10 +226,15 @@ class Serialization { 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); + JSONAssert.assertEquals(""" + { + "version": { + "major-version": 1, + "minor-version": 2, + "revision": 3 + } + } + """, serialize(d), false); } @Test @@ -239,23 +244,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 @@ -308,13 +323,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); } } @@ -322,8 +341,12 @@ 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); @@ -333,12 +356,19 @@ void testCreateJobRequestSimple() throws IOException { @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); @@ -354,8 +384,11 @@ void testCreateJobRequestComplex() throws IOException { @Test void testPowerRequest() throws IOException { - var obj = "{\"power\": \"ON\"}"; - var mp = deserialize(obj, MachinePower.class); + var mp = deserialize(""" + { + "power": "ON" + } + """, MachinePower.class); assertEquals(ON, mp.getPower()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java index 6feba8c25f..0554cc9153 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java @@ -78,13 +78,13 @@ public Version(String major, String minor, String rev) { } // This RE is in Extended mode syntax, which COMMENTS enables - private static final Pattern VERSION_RE = Pattern.compile( - " ^(\"?) # A optional quote\n" - + "(?\\d+) # A major version number\n" - + "(?:\\.(?\\d+) # An optional minor version number\n" - + "(?:\\.(?\\d+))? # An optional revision number\n" - + ")?\\1$ # Back reference to optional quote\n", - Pattern.COMMENTS); + private static final Pattern VERSION_RE = Pattern.compile(""" + ^("?) # A optional quote + (?\\d+) # A major version number + (?:\\.(?\\d+) # An optional minor version number + (?:\\.(?\\d+))? # An optional revision number + )? \\1 $ # Back reference to optional quote + """, Pattern.COMMENTS); /** * Create a version number. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/VersionInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/VersionInfo.java index d2eb9224c2..b203cae3f9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/VersionInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/VersionInfo.java @@ -18,6 +18,7 @@ import static java.lang.Byte.toUnsignedInt; import static java.lang.Short.toUnsignedInt; +import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static java.time.Instant.ofEpochSecond; import static java.time.ZoneOffset.UTC; @@ -145,10 +146,9 @@ public VersionInfo(ByteBuffer buffer, boolean isBMP) { @Override public String toString() { - return "VersionInfo(" + core + " (phys:" + physicalCPUID - + "), version: " + versionNumber + ", " + name + "/" + hardware - + ", " + ofInstant(ofEpochSecond(buildDate, 0), UTC) - .format(ISO_INSTANT) - + ")"; + return format("VersionInfo(%s (phys:%d), version: %s, %s/%s, %s)", // + core, physicalCPUID, versionNumber, name, hardware, + ofInstant(ofEpochSecond(buildDate, 0), UTC) + .format(ISO_INSTANT)); } } diff --git a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestIobufRequest.java b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestIobufRequest.java index 0a9d7428a6..9bfd7f31a2 100644 --- a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestIobufRequest.java +++ b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestIobufRequest.java @@ -33,11 +33,13 @@ public class TestIobufRequest { @Test public void testCorrect() throws IOException { - var input = "{\n" - + " \"/some/path/abc.aplx\": [ [0,0,1], [0,0,2], [0,0,3] ],\n" - + " \"/some/path/def.aplx\": [ [0,1,1], [0,1,2], [0,1,3] ],\n" - + " \"/some/path/ghi.aplx\": [ [1,0,1], [1,0,2], [0,0,4] ]\n" - + "}"; + var input = """ + { + "/some/path/abc.aplx": [ [0,0,1], [0,0,2], [0,0,3] ], + "/some/path/def.aplx": [ [0,1,1], [0,1,2], [0,1,3] ], + "/some/path/ghi.aplx": [ [1,0,1], [1,0,2], [0,0,4] ] + } + """; var req = createMapper().readValue(input, IobufRequest.class); var details = req.getRequestDetails(); @@ -59,11 +61,13 @@ public void testCorrect() throws IOException { @Test public void testIncorrect() { // Overlap between the core subsets; THIS IS BAD and shouldn't happen - var input = "{\n" - + " \"/some/path/abc.aplx\": [ [0,0,1], [0,0,2], [0,0,3] ],\n" - + " \"/some/path/def.aplx\": [ [0,1,1], [0,1,2], [0,0,3] ],\n" - + " \"/some/path/ghi.aplx\": [ [0,0,1], [1,0,2], [0,0,4] ]\n" - + "}"; + var input = """ + { + "/some/path/abc.aplx": [ [0,0,1], [0,0,2], [0,0,3] ], + "/some/path/def.aplx": [ [0,1,1], [0,1,2], [0,0,3] ], + "/some/path/ghi.aplx": [ [0,0,1], [1,0,2], [0,0,4] ] + } + """; var e = assertThrows(ValueInstantiationException.class, () -> createMapper().readValue(input, IobufRequest.class)); diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipDetails.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipDetails.java index 002ec171aa..5d9814d78c 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipDetails.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipDetails.java @@ -27,8 +27,14 @@ public class TestChipDetails { @Test public void testFromJson() throws IOException { - var json = "{\"cores\": 18, \"deadLinks\": [3, 4, 5], " - + "\"ipAddress\": \"130.88.192.243\", \"ethernet\":[0, 0]}"; + var json = """ + { + "cores": 18, + "deadLinks": [3, 4, 5], + "ipAddress": "130.88.192.243", + "ethernet": [0, 0] + } + """; /* * String json = "{\"cores\": 18, \"ipAddress\": \"130.88.192.243\", * \"ethernet\":[0, 0]}"; diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipbean.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipbean.java index a4d6a16072..4d16f5821f 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipbean.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestChipbean.java @@ -28,9 +28,16 @@ public class TestChipbean { @Test public void testFromJson() throws IOException { - var json = "[1, 2, {\"cores\": 17, \"ethernet\": [2, 3]}, {" - + "\"sdram\": 123469692, " - + "\"routerEntries\": 1013, \"monitors\": 2}]"; + var json = """ + [1, 2, { + "cores": 17, + "ethernet": [2, 3] + }, { + "sdram": 123469692, + "routerEntries": 1013, + "monitors": 2 + }] + """; var mapper = MapperFactory.createMapper(); var fromJson = mapper.readValue(json, ChipBean.class); assertNotNull(fromJson); diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/tags/TestIPTag.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/tags/TestIPTag.java index d41ebef87e..e097ad8add 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/tags/TestIPTag.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/tags/TestIPTag.java @@ -187,12 +187,18 @@ public void testEquals() throws UnknownHostException { @Test public void testFromJson() throws IOException { - var json = " {\"x\": 0, \"y\": 0, " - + "\"boardAddress\": \"192.168.240.253\", " - + "\"targetAddress\": \"localhost\", \"stripSDP\": true, " - + "\"tagID\": 1, \"trafficIdentifier\": \"DATA_SPEED_UP\"}"; var mapper = MapperFactory.createMapper(); - var fromJson = mapper.readValue(json, IPTag.class); + var fromJson = mapper.readValue(""" + { + "x": 0, + "y": 0, + "boardAddress": "192.168.240.253", + "targetAddress": "localhost", + "stripSDP": true, + "tagID": 1, + "trafficIdentifier": "DATA_SPEED_UP" + } + """, IPTag.class); assertNotNull(fromJson); } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java index bb77af326e..556dd8eef4 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQL.java @@ -39,57 +39,77 @@ private SQL() { @Parameter("y") @Parameter("processor") @GeneratesID - static final String INSERT_LOCATION = - "INSERT INTO core(x, y, processor) VALUES(?, ?, ?)"; + static final String INSERT_LOCATION = """ + INSERT INTO core( + x, y, processor) + VALUES(?, ?, ?) + """; /** Find an existing (x,y,p) record. */ @Parameter("x") @Parameter("y") @Parameter("processor") @ResultColumn("core_id") - static final String GET_LOCATION = "SELECT core_id FROM core" - + " WHERE x = ? AND y = ? AND processor = ? LIMIT 1"; + static final String GET_LOCATION = """ + SELECT core_id + FROM core + WHERE x = ? AND y = ? AND processor = ? + LIMIT 1 + """; /** Create an empty region record. */ @Parameter("core_id") @Parameter("local_region_index") @Parameter("address") @GeneratesID - static final String INSERT_REGION = "INSERT INTO " - + "region(core_id, local_region_index, address)" - + " VALUES (?, ?, ?)"; + static final String INSERT_REGION = """ + INSERT INTO region( + core_id, local_region_index, address) + VALUES (?, ?, ?) + """; /** Find an existing region record. */ @Parameter("core_id") @Parameter("local_region_index") @ResultColumn("region_id") - static final String GET_REGION = "SELECT region_id FROM region WHERE " - + "core_id = ? AND local_region_index = ? LIMIT 1"; + static final String GET_REGION = """ + SELECT region_id + FROM region + WHERE core_id = ? AND local_region_index = ? + LIMIT 1 + """; /** Append content to a region record. */ @Parameter("content_to_add") @Parameter("content_len") @Parameter("append_time") @Parameter("region_id") - static final String ADD_CONTENT = - "UPDATE region SET content = CAST(? AS BLOB), content_len = ?, " - + "fetches = 1, append_time = ? WHERE region_id = ?"; + static final String ADD_CONTENT = """ + UPDATE region + SET content = CAST(? AS BLOB), content_len = ?, + fetches = 1, append_time = ? + WHERE region_id = ? + """; /** Prepare a region record for handling content in the extra table. */ @Parameter("append_time") @Parameter("region_id") - static final String PREP_EXTRA_CONTENT = - "UPDATE region SET fetches = fetches + 1, append_time = ? " - + "WHERE region_id = ?"; + static final String PREP_EXTRA_CONTENT = """ + UPDATE region + SET fetches = fetches + 1, append_time = ? + WHERE region_id = ? + """; /** Add content to a new row in the extra table. */ @Parameter("region_id") @Parameter("content_to_add") @Parameter("content_len") @GeneratesID - static final String ADD_EXTRA_CONTENT = - "INSERT INTO region_extra(region_id, content, content_len) " - + "VALUES (?, CAST(? AS BLOB), ?)"; + static final String ADD_EXTRA_CONTENT = """ + INSERT INTO region_extra( + region_id, content, content_len) + VALUES (?, CAST(? AS BLOB), ?) + """; /** * Discover whether region in the main region table is available for storing @@ -97,21 +117,25 @@ private SQL() { */ @Parameter("region_id") @ResultColumn("existing") - static final String GET_MAIN_CONTENT_AVAILABLE = - "SELECT COUNT(*) AS existing FROM region " - + "WHERE region_id = ? AND fetches = 0"; + static final String GET_MAIN_CONTENT_AVAILABLE = """ + SELECT COUNT(*) AS existing + FROM region + WHERE region_id = ? AND fetches = 0 + """; /** * Determine just how much content there is for a row, overall. */ @Parameter("region_id") @ResultColumn("len") - static final String GET_CONTENT_TOTAL_LENGTH = - "SELECT r.content_len + (" - + " SELECT SUM(x.content_len) " - + " FROM region_extra AS x " - + " WHERE x.region_id = r.region_id" - + ") AS len FROM region AS r WHERE region_id = ?"; + static final String GET_CONTENT_TOTAL_LENGTH = """ + SELECT r.content_len + ( + SELECT SUM(x.content_len) + FROM region_extra AS x + WHERE x.region_id = r.region_id) AS len + FROM region AS r + WHERE region_id = ? + """; /** Fetch the current variable state of a region record. */ @Parameter("x") @@ -123,38 +147,46 @@ private SQL() { @ResultColumn("fetches") @ResultColumn("append_time") @ResultColumn("region_id") - static final String FETCH_RECORDING = - "SELECT content, content_len, fetches, append_time, region_id " - + "FROM region_view" - + " WHERE x = ? AND y = ? AND processor = ?" - + " AND local_region_index = ? LIMIT 1"; + static final String FETCH_RECORDING = """ + SELECT content, content_len, fetches, append_time, region_id + FROM region_view + WHERE x = ? AND y = ? AND processor = ? AND local_region_index = ? + LIMIT 1 + """; /** Fetch the current variable state of a region record. */ @Parameter("region_id") @ResultColumn("content") @ResultColumn("content_len") - static final String FETCH_EXTRA_RECORDING = - "SELECT content, content_len FROM region_extra" - + " WHERE region_id = ? ORDER BY extra_id ASC"; + static final String FETCH_EXTRA_RECORDING = """ + SELECT content, content_len + FROM region_extra + WHERE region_id = ? + ORDER BY extra_id ASC + """; /** List the cores with storage. */ @Parameters({}) @ResultColumn("x") @ResultColumn("y") @ResultColumn("processor") - static final String GET_CORES_WITH_STORAGE = - "SELECT DISTINCT x, y, processor FROM region_view" - + " ORDER BY x, y, processor"; + static final String GET_CORES_WITH_STORAGE = """ + SELECT DISTINCT x, y, processor + FROM region_view + ORDER BY x, y, processor + """; /** List the regions of a core with storage. */ @Parameter("x") @Parameter("y") @Parameter("processor") @ResultColumn("local_region_index") - static final String GET_REGIONS_WITH_STORAGE = - "SELECT DISTINCT local_region_index FROM region_view" - + " WHERE x = ? AND y = ? AND processor = ?" - + " ORDER BY local_region_index"; + static final String GET_REGIONS_WITH_STORAGE = """ + SELECT DISTINCT local_region_index + FROM region_view + WHERE x = ? AND y = ? AND processor = ? + ORDER BY local_region_index + """; // ----------------------------------------------------------------- // Data loading ---------------------------------------------------- @@ -163,10 +195,12 @@ private SQL() { /** Count the data specifications in the DB that are still to be run. */ @Parameters({}) @ResultColumn("count_content") - static final String COUNT_WORK = - "SELECT count(content) AS count_content FROM core_view " - + "WHERE start_address IS NULL AND " - + "app_id IS NOT NULL AND content IS NOT NULL"; + static final String COUNT_WORK = """ + SELECT count(content) AS count_content + FROM core_view + WHERE start_address IS NULL + AND app_id IS NOT NULL AND content IS NOT NULL + """; /** List the ethernets described in the database. */ @Parameters({}) @@ -174,9 +208,10 @@ private SQL() { @ResultColumn("ethernet_x") @ResultColumn("ethernet_y") @ResultColumn("ip_address") - static final String LIST_ETHERNETS = - "SELECT DISTINCT ethernet_id, ethernet_x, ethernet_y, ip_address" - + " FROM core_view"; + static final String LIST_ETHERNETS = """ + SELECT DISTINCT ethernet_id, ethernet_x, ethernet_y, ip_address + FROM core_view + """; /** List the cores of a ethernets with a data specification to run. */ @Parameter("ethernet_id") @@ -186,11 +221,12 @@ private SQL() { @ResultColumn("processor") @ResultColumn("app_id") @ResultColumn("memory_used") - static final String LIST_CORES_TO_LOAD = - "SELECT core_id, x, y, processor, app_id, memory_used " - + "FROM core_view " - + "WHERE ethernet_id = ? AND app_id IS NOT NULL " - + "AND content IS NOT NULL"; + static final String LIST_CORES_TO_LOAD = """ + SELECT core_id, x, y, processor, app_id, memory_used + FROM core_view + WHERE ethernet_id = ? AND app_id IS NOT NULL + AND content IS NOT NULL + """; /** List the cores of a ethernets with a data specification to run. */ @Parameter("ethernet_id") @@ -201,17 +237,22 @@ private SQL() { @ResultColumn("processor") @ResultColumn("app_id") @ResultColumn("memory_used") - static final String LIST_CORES_TO_LOAD_FILTERED = - "SELECT core_id, x, y, processor, app_id, memory_used " - + "FROM core_view " - + "WHERE ethernet_id = ? AND is_system = ? " - + "AND app_id IS NOT NULL AND content IS NOT NULL"; + static final String LIST_CORES_TO_LOAD_FILTERED = """ + SELECT core_id, x, y, processor, app_id, memory_used + FROM core_view + WHERE ethernet_id = ? AND is_system = ? + AND app_id IS NOT NULL AND content IS NOT NULL + """; /** Get the data specification to run for a particular core. */ @Parameter("core_id") @ResultColumn("content") - static final String GET_CORE_DATA_SPEC = - "SELECT content FROM core_view WHERE core_id = ? LIMIT 1"; + static final String GET_CORE_DATA_SPEC = """ + SELECT content + FROM core_view + WHERE core_id = ? + LIMIT 1 + """; /** * Store the metadata about the loaded data generated by data specification @@ -221,7 +262,9 @@ private SQL() { @Parameter("memory_used") @Parameter("memory_written") @Parameter("core_id") - static final String ADD_LOADING_METADATA = "UPDATE core " - + "SET start_address = ?, memory_used = ?, memory_written = ? " - + "WHERE core_id = ?"; + static final String ADD_LOADING_METADATA = """ + UPDATE core + SET start_address = ?, memory_used = ?, memory_written = ? + WHERE core_id = ? + """; } diff --git a/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/CredentialDB.java b/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/CredentialDB.java index 8d9f170d21..c341f794e4 100644 --- a/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/CredentialDB.java +++ b/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/CredentialDB.java @@ -53,10 +53,16 @@ public CredentialDB(File databaseFile) throws SQLException, IOException { db = (SQLiteConnection) config.createConnection( "jdbc:sqlite:" + databaseFile.getCanonicalPath()); try (var s = db.createStatement()) { - s.execute("CREATE TABLE IF NOT EXISTS tokens(" - + "client TEXT UNIQUE NOT NULL, token TEXT NOT NULL)"); - s.execute("CREATE TABLE IF NOT EXISTS users(" - + "name TEXT UNIQUE NOT NULL, pass TEXT NOT NULL)"); + s.execute(""" + CREATE TABLE IF NOT EXISTS tokens( + client TEXT UNIQUE NOT NULL, + token TEXT NOT NULL) + """); + s.execute(""" + CREATE TABLE IF NOT EXISTS users( + name TEXT UNIQUE NOT NULL, + pass TEXT NOT NULL) + """); } } @@ -80,8 +86,11 @@ final class DBContainedCredentials implements EBRAINSDevCredentials { /** Make an instance. */ DBContainedCredentials() throws SQLException, IllegalStateException { try (var s = db.createStatement(); - var rs = s.executeQuery( - "SELECT name, pass FROM users LIMIT 1")) { + var rs = s.executeQuery(""" + SELECT name, pass + FROM users + LIMIT 1 + """)) { if (rs.next()) { name = rs.getString("name"); pass = rs.getString("pass"); @@ -113,8 +122,11 @@ public String getPass() { */ final void saveCredentials(EBRAINSDevCredentials creds) throws SQLException { - try (var s = db.prepareStatement( - "INSERT OR REPLACE INTO users(name, pass) VALUES (?, ?)")) { + try (var s = db.prepareStatement(""" + INSERT OR REPLACE INTO users( + name, pass) + VALUES (?, ?) + """)) { s.setString(1, creds.getUser()); s.setString(2, creds.getPass()); s.executeUpdate(); @@ -129,8 +141,12 @@ final void saveCredentials(EBRAINSDevCredentials creds) * @return The token, or {@code null} if no token is available. */ final String getToken(String clientId) { - try (var s = db.prepareStatement( - "SELECT token FROM tokens WHERE client = ? LIMIT 1")) { + try (var s = db.prepareStatement(""" + SELECT token + FROM tokens + WHERE client = ? + LIMIT 1 + """)) { s.setString(1, requireNonNull(clientId)); try (var rs = s.executeQuery()) { while (rs.next()) { @@ -158,9 +174,11 @@ final String getToken(String clientId) { * If database access fails. */ final void saveToken(String clientId, String token) throws SQLException { - try (var s = db.prepareStatement( - "INSERT OR REPLACE INTO tokens(client, token) " - + "VALUES (?, ?)")) { + try (var s = db.prepareStatement(""" + INSERT OR REPLACE INTO tokens( + client, token) + VALUES (?, ?) + """)) { s.setString(1, clientId); s.setString(2, token); s.executeUpdate(); From 2662bda6a020f58e29dd719dd5a1ccf21e7b9cfa Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 29 Nov 2022 09:26:35 +0000 Subject: [PATCH 011/194] New style instanceof --- .../spinnaker/alloc/admin/DirInfo.java | 6 +--- .../alloc/admin/MachineDefinitionLoader.java | 3 +- .../spinnaker/alloc/allocator/Spalloc.java | 3 +- .../spinnaker/alloc/bmp/BMPController.java | 20 ++++++------ .../alloc/bmp/TransceiverFactory.java | 12 +++---- .../spinnaker/alloc/compat/SaneParameter.java | 4 +-- .../spinnaker/alloc/compat/Utils.java | 8 ++--- .../spinnaker/alloc/compat/V1TaskImpl.java | 8 ++--- .../spinnaker/alloc/db/DatabaseEngine.java | 32 +++++++++---------- .../manchester/spinnaker/alloc/db/Utils.java | 7 ++-- .../spinnaker/alloc/model/BoardCoords.java | 13 +++----- .../spinnaker/alloc/model/ConnectionInfo.java | 9 ++---- .../security/AccessDeniedExceptionMapper.java | 6 ++-- ...nyTypeMethodSecurityExpressionHandler.java | 4 +-- .../security/AppAuthTransformationFilter.java | 3 +- .../alloc/security/LocalAuthProviderImpl.java | 18 ++++------- .../alloc/security/SecurityConfig.java | 5 ++- .../spinnaker/alloc/security/Utils.java | 4 +-- .../alloc/web/RequestFailedException.java | 4 +-- .../spinnaker/alloc/client/BoardCoords.java | 9 ++---- .../connections/EIEIOConnection.java | 4 +-- .../spinnaker/messages/bmp/BMPLocation.java | 8 ++--- .../boot/SystemVariableBootValues.java | 6 ++-- .../messages/eieio/EIEIOMessageHandler.java | 8 ++--- .../spinnaker/messages/model/AppID.java | 6 +--- .../spinnaker/messages/model/Blacklist.java | 8 ++--- .../spinnaker/messages/model/Version.java | 8 ++--- .../spinnaker/messages/sdp/SDPHeader.java | 7 ++-- .../spinnaker/spalloc/SpallocConnection.java | 14 ++++---- .../spalloc/messages/BoardCoordinates.java | 7 ++-- .../messages/BoardPhysicalCoordinates.java | 9 ++---- .../spalloc/messages/Connection.java | 8 ++--- .../messages/JobsChangedNotification.java | 7 ++-- .../spinnaker/spalloc/messages/WhereIs.java | 19 +++++------ .../transceiver/ProcessException.java | 4 +-- .../spinnaker/transceiver/Transceiver.java | 26 +++++++-------- .../spinnaker/data_spec/Executor.java | 6 ++-- .../spinnaker/data_spec/Functions.java | 6 ++-- .../data_spec/MemoryRegionCollection.java | 22 ++++++------- .../spinnaker/data_spec/Reference.java | 2 +- .../spinnaker/data_spec/Generator.java | 12 +++---- .../front_end/download/DataGatherer.java | 5 +-- .../dse/FastExecuteDataSpecification.java | 3 +- .../dse/HostExecuteDataSpecification.java | 3 +- .../ac/manchester/spinnaker/machine/Chip.java | 2 +- .../spinnaker/machine/ChipLocation.java | 7 ++-- .../spinnaker/machine/CoreLocation.java | 7 ++-- .../spinnaker/machine/CoreSubsets.java | 7 ++-- .../ac/manchester/spinnaker/machine/Link.java | 3 +- .../manchester/spinnaker/machine/Machine.java | 2 +- .../spinnaker/machine/MachineDimensions.java | 7 ++-- .../spinnaker/machine/MemoryLocation.java | 6 +--- .../spinnaker/machine/Processor.java | 7 ++-- .../spinnaker/machine/RegionLocation.java | 8 ++--- .../spinnaker/machine/board/BMPBoard.java | 6 +--- .../spinnaker/machine/board/BMPCoords.java | 7 ++-- .../machine/board/PhysicalCoords.java | 7 ++-- .../spinnaker/machine/board/TriadCoords.java | 7 ++-- .../machine/datalinks/FPGALinkData.java | 8 ++--- .../machine/datalinks/InetIdTuple.java | 7 ++-- .../machine/datalinks/SpinnakerLinkData.java | 7 ++-- .../spinnaker/machine/tags/IPTag.java | 12 +++---- .../spinnaker/machine/tags/ReverseIPTag.java | 9 ++---- .../storage/sqlite/SQLiteDataSpecStorage.java | 22 ++++++------- .../storage/threading/OTResults.java | 8 ++--- .../manchester/spinnaker/tools/GetDevId.java | 3 +- 66 files changed, 206 insertions(+), 339 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/DirInfo.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/DirInfo.java index 02ee0f5c5f..aedf092bd8 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/DirInfo.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/DirInfo.java @@ -98,11 +98,7 @@ public static DirInfo get(int z, Direction direction) { @Override public boolean equals(Object o) { - if (!(o instanceof DirInfo)) { - return false; - } - var di = (DirInfo) o; - return z == di.z && dir == di.dir; + return (o instanceof DirInfo di) && (z == di.z) && (dir == di.dir); } @Override diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 1d7280e530..1102aa44db 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -806,8 +806,7 @@ private Optional makeLink(Updates sql, Machine machine, there, d2); return sql.makeLink.key(b1, d1, b2, d2, !dead); } catch (DataAccessException e) { - if (e.getMostSpecificCause() instanceof SQLiteException) { - var exn = (SQLiteException) e.getMostSpecificCause(); + if (e.getMostSpecificCause() instanceof SQLiteException exn) { /* * If the CHECK constraint says no, just ignore; we'll do the * link from the other direction. This does mean we're doing too 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 1d94bd9b63..22071527b1 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 @@ -621,8 +621,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)) { 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 5b85123555..c3fd30cd53 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 @@ -1416,10 +1416,10 @@ void backgroundThread() { * this queue. */ var r = requests.poll(); - if (r instanceof PowerRequest) { - processRequest((PowerRequest) r); - } else if (r instanceof BlacklistRequest) { - processRequest((BlacklistRequest) r); + if (r instanceof PowerRequest pr) { + processRequest(pr); + } else if (r instanceof BlacklistRequest br) { + processRequest(br); } /* @@ -1561,8 +1561,8 @@ private void processRequest(PowerRequest request) private Map getControllers(Request request) throws IOException, SpinnmanException { try { - if (request instanceof PowerRequest) { - return getControllersForPower((PowerRequest) request); + if (request instanceof PowerRequest pr) { + return getControllersForPower(pr); } else { return getControllersForBlacklisting( (BlacklistRequest) request); @@ -1570,10 +1570,10 @@ private Map getControllers(Request request) } catch (BeanInitializationException | BeanCreationException e) { // Smuggle the exception out from the @PostConstruct method var cause = e.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else if (cause instanceof SpinnmanException) { - throw (SpinnmanException) cause; + if (cause instanceof IOException ioe) { + throw ioe; + } else if (cause instanceof SpinnmanException se) { + throw se; } throw e; } 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 e48275a484..8bff667357 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 @@ -131,12 +131,12 @@ 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; } 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 efdaf7bcdf..de1a6fb4fb 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 @@ -68,8 +68,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 2dd727c88b..682bc051f6 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 @@ -115,10 +115,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()); 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 c5986ba183..fa5c41854f 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 @@ -222,12 +222,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"); diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java index 4c43842aae..8073bd4271 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java @@ -895,15 +895,13 @@ public void close() { } private void cantWarning(String op, DataAccessException e) { - if (e.getMostSpecificCause() instanceof SQLiteException) { - var ex = (SQLiteException) e.getMostSpecificCause(); - if (ex.getMessage().contains( - "cannot " + op + " - no transaction is active")) { - log.warn( - "failed to {} transaction: " - + "current transaction holders are {}", - op, currentTransactionHolders()); - } + if (e.getMostSpecificCause() instanceof SQLiteException ex + && ex.getMessage().contains( + "cannot " + op + " - no transaction is active")) { + log.warn( + "failed to {} transaction: " + + "current transaction holders are {}", + op, currentTransactionHolders()); } } @@ -1190,16 +1188,16 @@ final void setParams(Object[] arguments) throws SQLException { int idx = 0; for (var arg : arguments) { // 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 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 8ea7c98bdb..a9580cc117 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 @@ -99,8 +99,8 @@ private static String trimSQLComments(String sql) { */ public static boolean isBusy(DataAccessException exception) { var root = exception.getMostSpecificCause(); - return root instanceof SQLiteException - && ((SQLiteException) root).getResultCode() == SQLITE_BUSY; + return (root instanceof SQLiteException exn) + && exn.getResultCode() == SQLITE_BUSY; } /** @@ -115,7 +115,7 @@ public static boolean isBusy(DataAccessException exception) { */ public static DataAccessException mapException(SQLException exception, String sql) { - if (!(exception instanceof SQLiteException)) { + if (!(exception instanceof SQLiteException exn)) { if (exception.getMessage().contains("no such column: ")) { return restack(new InvalidResultSetAccessException( exception.getMessage(), trimSQLComments(sql), @@ -124,7 +124,6 @@ public static DataAccessException mapException(SQLException exception, return restack(new UncategorizedSQLException( "general SQL exception", trimSQLComments(sql), exception)); } - var exn = (SQLiteException) exception; var msg = exn.getMessage(); boolean replaced = false; if (msg.contains("SQL error or missing database (")) { 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 6b19669451..1d6f1ad47e 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 @@ -176,14 +176,11 @@ public String getAddress() { @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; + return (o instanceof BoardCoords other) && (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); } @Override 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 b08842cbd8..e8b0df04cb 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 @@ -82,12 +82,9 @@ public String getHostname() { @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; + return (other instanceof ConnectionInfo c) + && Objects.equals(chip, c.chip) + && Objects.equals(hostname, c.hostname); } @Override 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 c7fbe925ad..5d54fea559 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 @@ -65,15 +65,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 3b0d1c95c3..bc654f0f7f 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 @@ -55,8 +55,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 31303cce9d..105e1122bc 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 @@ -91,8 +91,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/LocalAuthProviderImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/LocalAuthProviderImpl.java index b8c485e178..2f95616ddd 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 @@ -229,28 +229,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() @@ -1107,16 +1105,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/SecurityConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SecurityConfig.java index 65fc36884b..1336f4e87c 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 @@ -388,9 +388,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/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/Utils.java index 7dc3a04ed6..e31dfdd24f 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 @@ -74,8 +74,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/RequestFailedException.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java index a4b5eaa409..12be625f92 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 @@ -99,8 +99,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("^.*[.]", "") 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 d1146535c7..077d621832 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 @@ -168,12 +168,9 @@ public String toString() { @Override public boolean equals(Object other) { - if (!(other instanceof BoardCoords)) { - return false; - } - 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) + return (other instanceof BoardCoords o) && (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); } 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 4a3261987f..05b1039fe1 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 @@ -171,8 +171,8 @@ protected void sendCommand(EIEIOCommandID 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/messages/bmp/BMPLocation.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPLocation.java index ca2976a1f9..cb752d60cb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPLocation.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPLocation.java @@ -94,12 +94,8 @@ public int getP() { @Override public boolean equals(Object other) { - if (other instanceof BMPLocation) { - var bmp = (BMPLocation) other; - return bmp.cabinet == cabinet && bmp.frame == frame - && bmp.board == board; - } - return false; + return (other instanceof BMPLocation bmp) && (bmp.cabinet == cabinet) + && (bmp.frame == frame) && (bmp.board == board); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java index 85c94720fd..cf39f3cbdb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java @@ -83,13 +83,13 @@ public void setValue(SystemVariableDefinition systemVariable, switch (systemVariable.type) { case BYTE_ARRAY: var defbytes = (byte[]) values.get(systemVariable); - if (!(value instanceof byte[])) { + if (!(value instanceof byte[] newbytes)) { throw new IllegalArgumentException("need a byte array"); } - var newbytes = (byte[]) value; if (newbytes.length != defbytes.length) { throw new IllegalArgumentException( - "byte array length must be " + defbytes.length); + "byte array length must be " + defbytes.length + + " long"); } break; case ADDRESS: diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageHandler.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageHandler.java index 705c59798b..d7c9cb2742 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageHandler.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageHandler.java @@ -27,10 +27,10 @@ public interface EIEIOMessageHandler extends MessageHandler> { @Override default void handle(EIEIOMessage message) { - if (message instanceof EIEIOCommandMessage) { - handleCommand((EIEIOCommandMessage) message); - } else if (message instanceof EIEIODataMessage) { - handleData((EIEIODataMessage) message); + if (message instanceof EIEIOCommandMessage cmd) { + handleCommand(cmd); + } else if (message instanceof EIEIODataMessage data) { + handleData(data); } else { throw new IllegalArgumentException( "unsupported message type: " + message.getClass()); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java index 2298f66b7c..0e55b10189 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java @@ -56,11 +56,7 @@ public AppID(int appID) { @Override public boolean equals(Object o) { - if (o instanceof AppID) { - var other = (AppID) o; - return appID == other.appID; - } - return false; + return (o instanceof AppID other) && (appID == other.appID); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index d3ffa43ae3..103e86c79b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -496,12 +496,8 @@ public int hashCode() { @Override public boolean equals(Object object) { - if (object instanceof Blacklist) { - var other = (Blacklist) object; - return chips.equals(other.chips) && cores.equals(other.cores) - && links.equals(other.links); - } - return false; + return (object instanceof Blacklist other) && chips.equals(other.chips) + && cores.equals(other.cores) && links.equals(other.links); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java index 0554cc9153..95cd8ec25b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java @@ -116,12 +116,8 @@ private static int parsePossibleInt(String s) { @Override public boolean equals(Object other) { - if (!(other instanceof Version)) { - return false; - } - var v = (Version) other; - return majorVersion == v.majorVersion && minorVersion == v.minorVersion - && revision == v.revision; + return (other instanceof Version v) && (majorVersion == v.majorVersion) + && (minorVersion == v.minorVersion) && (revision == v.revision); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java index e8ad51473c..67a827255b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java @@ -177,11 +177,8 @@ public int hashCode() { @Override public boolean equals(Object other) { - if (!(other instanceof HasCoreLocation)) { - return false; - } - var c = (HasCoreLocation) other; - return x == c.getX() && y == c.getY() && p == c.getP(); + return (other instanceof HasCoreLocation c) && (x == c.getX()) + && (y == c.getY()) && (p == c.getP()); } }; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocConnection.java index 930da9ffe2..5c2d9e4000 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocConnection.java @@ -422,15 +422,13 @@ protected String call(Command command, Integer timeout) if (r == null) { continue; } - if (r instanceof ReturnResponse) { - // Success! - return ((ReturnResponse) r).getReturnValue(); - } else if (r instanceof ExceptionResponse) { - // Server error! - throw new SpallocServerException((ExceptionResponse) r); - } else if (r instanceof Notification) { + if (r instanceof ReturnResponse success) { + return success.getReturnValue(); + } else if (r instanceof ExceptionResponse serverError) { + throw new SpallocServerException(serverError); + } else if (r instanceof Notification notification) { // Got a notification, keep trying... - notifications.add((Notification) r); + notifications.add(notification); } else { throw new SpallocProtocolException( "bad response: " + r.getClass()); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java index f7349d3ceb..fdb4ab4831 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java @@ -98,11 +98,8 @@ public int getZ() { @Override public boolean equals(Object o) { - if (o instanceof BoardCoordinates) { - var other = (BoardCoordinates) o; - return x == other.x && y == other.y && z == other.z; - } - return false; + return (o instanceof BoardCoordinates other) && (x == other.x) + && (y == other.y) && (z == other.z); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java index 1dbe68f286..d926d9d5c3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java @@ -101,12 +101,9 @@ public Integer getBoard() { @Override public boolean equals(Object o) { - if (o instanceof BoardPhysicalCoordinates) { - var other = (BoardPhysicalCoordinates) o; - return cabinet == other.cabinet && frame == other.frame - && Objects.equals(board, other.board); - } - return false; + return (o instanceof BoardPhysicalCoordinates other) + && (cabinet == other.cabinet) && (frame == other.frame) + && Objects.equals(board, other.board); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java index a71df2dd82..21127c0682 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java @@ -75,12 +75,8 @@ public String getHostname() { @Override public boolean equals(Object other) { - if (other instanceof Connection) { - var c = (Connection) other; - return Objects.equals(chip, c.chip) - && Objects.equals(hostname, c.hostname); - } - return false; + return (other instanceof Connection c) && Objects.equals(chip, c.chip) + && Objects.equals(hostname, c.hostname); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java index 8cde062795..9dadebdfbe 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java @@ -56,11 +56,8 @@ void setJobsChanged(List jobsChanged) { @Override public boolean equals(Object other) { - if (!(other instanceof JobsChangedNotification)) { - return false; - } - return jobsChanged - .equals(((JobsChangedNotification) other).jobsChanged); + return (other instanceof JobsChangedNotification jcn) + && jobsChanged.equals(jcn.jobsChanged); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java index 78cb9d7b6f..db6837d7e2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java @@ -139,17 +139,14 @@ public BoardPhysicalCoordinates getPhysical() { @Override public boolean equals(Object o) { - if (o instanceof WhereIs) { - var other = (WhereIs) o; - return Objects.equals(jobChip, other.jobChip) - && Objects.equals(jobId, other.jobId) - && Objects.equals(chip, other.chip) - && Objects.equals(logical, other.logical) - && Objects.equals(machine, other.machine) - && Objects.equals(boardChip, other.boardChip) - && Objects.equals(physical, other.physical); - } - return false; + return (o instanceof WhereIs other) + && Objects.equals(jobChip, other.jobChip) + && Objects.equals(jobId, other.jobId) + && Objects.equals(chip, other.chip) + && Objects.equals(logical, other.logical) + && Objects.equals(machine, other.machine) + && Objects.equals(boardChip, other.boardChip) + && Objects.equals(physical, other.physical); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java index 334548ef98..177315c19c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java @@ -71,8 +71,8 @@ private ProcessException(HasCoreLocation core, */ static ProcessException makeInstance(HasCoreLocation core, Throwable cause) throws InterruptedException { - if (requireNonNull(cause) instanceof UnexpectedResponseCodeException) { - var urc = (UnexpectedResponseCodeException) cause; + if (requireNonNull( + cause) instanceof UnexpectedResponseCodeException urc) { if (urc.response == null) { return new ProcessException(core, cause, null); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index e158c1e36b..01ff05fd65 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -554,8 +554,8 @@ public Transceiver(Machine machine) null, null, false, generateScampConnections(machine), null, null); this.machine = machine; - if (scpSelector instanceof MachineAware) { - ((MachineAware) scpSelector).setMachine(machine); + if (scpSelector instanceof MachineAware ma) { + ma.setMachine(machine); } log.info("known connections to this transceiver: {}", udpScpConnections); @@ -652,33 +652,31 @@ private ConnectionSelector makeConnectionSelector() { */ private void identifyConnection(Connection conn) { // locate the only boot send conn - if (conn instanceof BootConnection) { + if (conn instanceof BootConnection bc) { if (bootConnection != null) { throw new IllegalArgumentException( "Only a single BootSender can be specified"); } - bootConnection = (BootConnection) conn; + bootConnection = bc; } // Locate any connections listening on a UDP port - if (conn instanceof UDPConnection) { - registerConnection((UDPConnection) conn); + if (conn instanceof UDPConnection udpc) { + registerConnection(udpc); } // Locate any connections that can send SDP - if (conn instanceof SDPConnection) { - sdpConnections.add((SDPConnection) conn); + if (conn instanceof SDPConnection sdpc) { + sdpConnections.add(sdpc); } // Locate any connections that can send and receive SCP // If it is a BMP connection, add it here - if (conn instanceof BMPConnection) { - var bmpc = (BMPConnection) conn; + if (conn instanceof BMPConnection bmpc) { bmpConnections.add(bmpc); bmpSelectors.put(bmpc.getCoords(), new SingletonConnectionSelector<>(bmpc)); - } else if (conn instanceof SCPConnection) { - var scpc = (SCPConnection) conn; + } else if (conn instanceof SCPConnection scpc) { scpConnections.add(scpc); udpScpConnections.put(scpc.getRemoteIPAddress(), scpc); } @@ -911,8 +909,8 @@ void updateMachine() machine = machine.rebuild(); // update the SCAMP selector with the machine - if (scpSelector instanceof MachineAware) { - ((MachineAware) scpSelector).setMachine(machine); + if (scpSelector instanceof MachineAware ma) { + ma.setMachine(machine); } /* diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java index 29fca8ba05..b649e77568 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java @@ -185,8 +185,7 @@ public MemoryRegion getRegion(int regionID) { public void setBaseAddress(MemoryLocation startAddress) { int nextOffset = APP_PTR_TABLE_BYTE_SIZE; for (var reg : memRegions) { - if (reg instanceof MemoryRegionReal) { - var r = (MemoryRegionReal) reg; + if (reg instanceof MemoryRegionReal r) { r.setRegionBase(startAddress.add(nextOffset)); nextOffset += r.getAllocatedSize(); } @@ -216,9 +215,8 @@ public void addPointerTable(ByteBuffer buffer) { for (var reg : memRegions) { if (reg != null) { buffer.putInt(reg.getRegionBase().address); - if (reg instanceof MemoryRegionReal) { + if (reg instanceof MemoryRegionReal regReal) { // Work out the checksum - var regReal = (MemoryRegionReal) reg; int nWords = ceildiv(regReal.getMaxWritePointer(), INT_SIZE); var buf = regReal.getRegionData().duplicate() diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java index 62f861cdd1..cf0fa022bb 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java @@ -368,11 +368,10 @@ public void setWritePointer() throws DataSpecificationException { } var reg = getRegion(); - if (!(reg instanceof MemoryRegionReal)) { + if (!(reg instanceof MemoryRegionReal r)) { throw new NoRegionSelectedException( "no current region has been selected"); } - var r = (MemoryRegionReal) reg; if (r.isUnfilled()) { throw new RegionUnfilledException(currentRegion, SET_WR_PTR); } @@ -439,11 +438,10 @@ private void writeToMemory(byte[] array, Commands command) throw new NoRegionSelectedException(command); } var reg = getRegion(); - if (!(reg instanceof MemoryRegionReal)) { + if (!(reg instanceof MemoryRegionReal r)) { throw new RegionNotAllocatedException(currentRegion, command); } - var r = (MemoryRegionReal) reg; if (r.isUnfilled()) { throw new RegionUnfilledException(currentRegion, command); } diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegionCollection.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegionCollection.java index 275c291629..8959108b34 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegionCollection.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegionCollection.java @@ -109,8 +109,8 @@ public boolean isEmpty(int regionID) { */ public boolean isUnfilled(int regionID) { return isEmpty(regionID) - || !(regions[regionID] instanceof MemoryRegionReal) - || ((MemoryRegionReal) regions[regionID]).isUnfilled(); + || !(regions[regionID] instanceof MemoryRegionReal r) + || r.isUnfilled(); } /** @@ -121,8 +121,8 @@ public boolean isUnfilled(int regionID) { * @return The size of the region. Empty regions have zero size. */ public int getSize(int regionID) { - return !(regions[regionID] instanceof MemoryRegionReal) ? 0 - : ((MemoryRegionReal) regions[regionID]).getAllocatedSize(); + return !(regions[regionID] instanceof MemoryRegionReal r) ? 0 + : r.getAllocatedSize(); } /** @@ -131,7 +131,7 @@ public int getSize(int regionID) { * @return How many regions have been set. */ public int countUsedRegions() { - return (int) stream().filter(r -> r != null).count(); + return (int) stream().filter(Objects::nonNull).count(); } /** @@ -297,12 +297,12 @@ public void clear() { @Override public boolean equals(Object o) { Object[] a; - if (o instanceof MemoryRegionCollection) { - a = ((MemoryRegionCollection) o).regions; - } else if (o instanceof Collection) { - a = ((Collection) o).toArray(); - } else if (o instanceof MemoryRegion[]) { - a = (MemoryRegion[]) o; + if (o instanceof MemoryRegionCollection mrc) { + a = mrc.regions; + } else if (o instanceof Collection c) { + a = c.toArray(); + } else if (o instanceof MemoryRegion[] ary) { + a = ary; } else { return false; } diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Reference.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Reference.java index 572017d40e..a039febb24 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Reference.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Reference.java @@ -45,6 +45,6 @@ public int hashCode() { @Override public boolean equals(Object other) { - return (other instanceof Reference) && ((Reference) other).ref == ref; + return (other instanceof Reference r) && r.ref == ref; } } diff --git a/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java b/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java index 3dc2cb67c3..5974ec900c 100644 --- a/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java +++ b/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java @@ -214,12 +214,12 @@ private void command(Commands command, int length, int usage, for (int i = 0; i < arguments.length; i += 2) { var f = (Field) arguments[i]; var val = arguments[i + 1]; - if (val instanceof Boolean) { - word |= (((Boolean) val) ? 1 : 0) << f.offset; - } else if (val instanceof Enum && !(val instanceof Field)) { - word |= ((Enum) val).ordinal() << f.offset; - } else if (val instanceof Number) { - word |= ((Number) val).intValue() << f.offset; + if (val instanceof Boolean b) { + word |= (b ? 1 : 0) << f.offset; + } else if (val instanceof Enum e && !(val instanceof Field)) { + word |= e.ordinal() << f.offset; + } else if (val instanceof Number n) { + word |= n.intValue() << f.offset; } else { throw new IllegalArgumentException("arg: " + i + " = " + val); } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java index 20ccfba602..a720b6c074 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java @@ -422,10 +422,7 @@ private void fastDownload(List work, private void sanityCheck(List gatherers) { var sel = txrx.getScampConnectionSelector(); - MostDirectConnectionSelector s = null; - if (sel instanceof MostDirectConnectionSelector) { - s = (MostDirectConnectionSelector) sel; - } + var s = (sel instanceof MostDirectConnectionSelector ss ? ss : null); // Sanity check the inputs for (var g : gatherers) { diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index d5fd0431ed..b126f47b6f 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -255,10 +255,9 @@ private MemoryLocation malloc(CoreToLoad ctl, Integer bytesUsed) } private static MemoryRegionReal getRealRegionOrNull(MemoryRegion reg) { - if (!(reg instanceof MemoryRegionReal)) { + if (!(reg instanceof MemoryRegionReal r)) { return null; } - var r = (MemoryRegionReal) reg; if (r.isUnfilled() || r.getMaxWritePointer() <= 0) { return null; } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java index 9908d61ab4..a7fe2f68b8 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java @@ -322,10 +322,9 @@ private int writeRegion(HasCoreLocation core, MemoryRegionReal region, } private static MemoryRegionReal getRealRegionOrNull(MemoryRegion reg) { - if (!(reg instanceof MemoryRegionReal)) { + if (!(reg instanceof MemoryRegionReal r)) { return null; } - var r = (MemoryRegionReal) reg; if (r.isUnfilled() || r.getMaxWritePointer() <= 0) { return null; } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java index 6e10d0601d..cc9549ac29 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java @@ -444,7 +444,7 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - return (obj instanceof Chip) && isNull(difference((Chip) obj)); + return (obj instanceof Chip c) && isNull(difference(c)); } /** diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java index 0cf00d086f..48d7db127f 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java @@ -94,11 +94,8 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (obj instanceof ChipLocation) { - var that = (ChipLocation) obj; - return (x == that.x) && (y == that.y); - } - return false; + return (obj instanceof ChipLocation that) && (x == that.x) + && (y == that.y); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java index 79ce492fdc..464faccdf0 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java @@ -84,11 +84,8 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (obj instanceof CoreLocation) { - var that = (CoreLocation) obj; - return (x == that.x) && (y == that.y) && (p == that.p); - } - return false; + return (obj instanceof CoreLocation that) && (x == that.x) + && (y == that.y) && (p == that.p); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java index 4d754b5231..63dd82cc81 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java @@ -292,11 +292,8 @@ public int hashCode() { */ @Override public boolean equals(Object obj) { - if (obj instanceof CoreSubsets) { - var other = (CoreSubsets) obj; - return Objects.equals(locations, other.locations); - } - return false; + return (obj instanceof CoreSubsets other) + && Objects.equals(locations, other.locations); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java index 12c57ae12d..1bb1db6ad6 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java @@ -113,10 +113,9 @@ public Link(HasChipLocation source, int sourceLinkId, public boolean equals(Object obj) { if (this == obj) { return true; - } else if (!(obj instanceof Link)) { + } else if (!(obj instanceof Link other)) { return false; } - var other = (Link) obj; log.trace("Equals called {} {}", this, other); if (sourceLinkDirection != other.sourceLinkDirection) { return false; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java index b637f349a8..8d3d5ef7f6 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java @@ -943,7 +943,7 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - return (obj instanceof Machine) && isNull(difference((Machine) obj)); + return (obj instanceof Machine m) && isNull(difference(m)); } /** diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java index ce51aa3bb7..1160698048 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java @@ -44,11 +44,8 @@ public MachineDimensions(int width, int height) { @Override public boolean equals(Object o) { - if (o instanceof MachineDimensions) { - var dim = (MachineDimensions) o; - return (width == dim.width) && (height == dim.height); - } - return false; + return (o instanceof MachineDimensions dim) && (width == dim.width) + && (height == dim.height); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java index 0c9d47a686..fcc8936a87 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java @@ -96,11 +96,7 @@ public int hashCode() { @Override public boolean equals(Object other) { - if (!(other instanceof MemoryLocation)) { - return false; - } - var o = (MemoryLocation) other; - return o.address == address; + return (other instanceof MemoryLocation o) && (o.address == address); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Processor.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Processor.java index 7eb6289a26..9472e1c1b2 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Processor.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Processor.java @@ -123,11 +123,8 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof Processor)) { - return false; - } - var other = (Processor) obj; - return (processorId == other.processorId) + return (obj instanceof Processor other) + && (processorId == other.processorId) && (clockSpeed == other.clockSpeed) && (isMonitor == other.isMonitor) && (dtcmAvailable == other.dtcmAvailable); diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java index 14c989fdb3..c82544c5c1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java @@ -100,12 +100,8 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof RegionLocation)) { - return false; - } - var that = (RegionLocation) obj; - return (x == that.x) && (y == that.y) && (p == that.p) - && (region == that.region); + return (obj instanceof RegionLocation that) && (x == that.x) + && (y == that.y) && (p == that.p) && (region == that.region); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java index b86851c7ea..e297663184 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java @@ -48,10 +48,6 @@ public int hashCode() { @Override public boolean equals(Object o) { - if (o instanceof BMPBoard) { - var b = (BMPBoard) o; - return board == b.board; - } - return false; + return (o instanceof BMPBoard b) && (board == b.board); } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 3bfbca27a1..44f24d165e 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -122,11 +122,8 @@ public int getFrame() { @Override public boolean equals(Object obj) { - if (obj instanceof BMPCoords) { - var other = (BMPCoords) obj; - return cabinet == other.cabinet && frame == other.frame; - } - return false; + return (obj instanceof BMPCoords other) && (cabinet == other.cabinet) + && (frame == other.frame); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index f2ad307d20..6ce7cfdd0d 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -113,11 +113,8 @@ public PhysicalCoords(String serialForm) { @Override public boolean equals(Object obj) { - if (obj instanceof PhysicalCoords) { - var other = (PhysicalCoords) obj; - return c == other.c && f == other.f && b == other.b; - } - return false; + return (obj instanceof PhysicalCoords other) && (c == other.c) + && (f == other.f) && (b == other.b); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index c9b5b95689..583d824a93 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -146,11 +146,8 @@ public ChipLocation asChipLocation() { @Override public boolean equals(Object obj) { - if (obj instanceof TriadCoords) { - var other = (TriadCoords) obj; - return x == other.x && y == other.y && z == other.z; - } - return false; + return (obj instanceof TriadCoords other) && (x == other.x) + && (y == other.y) && (z == other.z); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/FPGALinkData.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/FPGALinkData.java index 6624777b8e..cd2a81c2f0 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/FPGALinkData.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/FPGALinkData.java @@ -66,12 +66,8 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj instanceof FPGALinkData) { - var other = (FPGALinkData) obj; - return sameAs(other) && (fpgaLinkId == other.fpgaLinkId) - && (fpgaId == other.fpgaId); - } - return false; + return (obj instanceof FPGALinkData other) && sameAs(other) + && (fpgaLinkId == other.fpgaLinkId) && (fpgaId == other.fpgaId); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java index 8d283b7e02..6104804d80 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java @@ -54,10 +54,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj instanceof InetIdTuple) { - var other = (InetIdTuple) obj; - return (id == other.id) && Objects.equals(address, other.address); - } - return false; + return (obj instanceof InetIdTuple other) && (id == other.id) + && Objects.equals(address, other.address); } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/SpinnakerLinkData.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/SpinnakerLinkData.java index a66c2503a3..bcc6d2a4e9 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/SpinnakerLinkData.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/SpinnakerLinkData.java @@ -60,11 +60,8 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj instanceof SpinnakerLinkData) { - var other = (SpinnakerLinkData) obj; - return sameAs(other) && (spinnakerLinkId == other.spinnakerLinkId); - } - return false; + return (obj instanceof SpinnakerLinkData other) && sameAs(other) + && (spinnakerLinkId == other.spinnakerLinkId); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java index a1137013cd..1cc24c6f3c 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java @@ -238,14 +238,10 @@ public ChipLocation getDestination() { @Override public boolean equals(Object o) { - if (o instanceof IPTag) { - var otherTag = (IPTag) o; - return partialEquals(otherTag) - && ipAddress.equals(otherTag.ipAddress) - && stripSDP == otherTag.stripSDP - && destination.equals(otherTag.destination); - } - return false; + return (o instanceof IPTag otherTag) && partialEquals(otherTag) + && ipAddress.equals(otherTag.ipAddress) + && stripSDP == otherTag.stripSDP + && destination.equals(otherTag.destination); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java index d5155c22de..1db357eed2 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java @@ -93,12 +93,9 @@ public int getSdpPort() { @Override public boolean equals(Object o) { - if (o instanceof ReverseIPTag) { - var otherTag = (ReverseIPTag) o; - return partialEquals(otherTag) && (sdpPort == otherTag.sdpPort) - && destination.equals(otherTag.destination); - } - return false; + return (o instanceof ReverseIPTag otherTag) && partialEquals(otherTag) + && (sdpPort == otherTag.sdpPort) + && destination.equals(otherTag.destination); } @Override diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index de58381207..718361a7b9 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -97,19 +97,19 @@ private static List listEthernetsToLoad(Connection conn) } private static EthernetImpl sanitise(Ethernet ethernet) { - if (!(ethernet instanceof EthernetImpl)) { - throw new IllegalArgumentException("can only list cores" - + " for ethernets described by this class"); + if (ethernet instanceof EthernetImpl eth) { + return eth; } - return (EthernetImpl) ethernet; + throw new IllegalArgumentException("can only list cores" + + " for ethernets described by this class"); } private static CoreToLoadImpl sanitise(CoreToLoad core, String desc) { - if (!(core instanceof CoreToLoadImpl)) { - throw new IllegalArgumentException( - "can only " + desc + " for cores described by this class"); + if (core instanceof CoreToLoadImpl ctl) { + return ctl; } - return (CoreToLoadImpl) core; + throw new IllegalArgumentException( + "can only " + desc + " for cores described by this class"); } @Override @@ -252,11 +252,7 @@ private CoreToLoadImpl(int id, int x, int y, int p, int appID, @Override public boolean equals(Object other) { - if (!(other instanceof CoreToLoadImpl)) { - return false; - } - var c = (CoreToLoadImpl) other; - return id == c.id; + return (other instanceof CoreToLoadImpl c) && id == c.id; } @Override diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTResults.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTResults.java index 836ce9a0df..306a69a0d3 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTResults.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTResults.java @@ -765,10 +765,10 @@ public Statement getStatement() throws SQLException { } validateThread(); var st = r.getStatement(); - if (st instanceof CallableStatement) { - return wrap((CallableStatement) st); - } else if (st instanceof PreparedStatement) { - return wrap((PreparedStatement) st); + if (st instanceof CallableStatement cs) { + return wrap(cs); + } else if (st instanceof PreparedStatement ps) { + return wrap(ps); } else { return wrap(st); } diff --git a/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/GetDevId.java b/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/GetDevId.java index 7a73120b47..9533296377 100644 --- a/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/GetDevId.java +++ b/keycloak-management-client/src/main/java/uk/ac/manchester/spinnaker/tools/GetDevId.java @@ -249,8 +249,7 @@ public static void main(String... arguments) log.debug("response:\n{}", mapper.writeValueAsString(cr)); } catch (ClientRegistrationException e) { log.error("failed", e); - if (e.getCause() instanceof HttpErrorException) { - var ex = (HttpErrorException) e.getCause(); + if (e.getCause() instanceof HttpErrorException ex) { log.info("status: {}", ex.getStatusLine().getStatusCode()); log.info("response: {}", ex.getErrorResponse()); } From f0453198a92c7b68b96d16569024d9abdb5c1daa Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 29 Nov 2022 09:43:24 +0000 Subject: [PATCH 012/194] Better built-in buffer slicing Replacing a utility function I wrote because it wasn't there --- .../spinnaker/alloc/bmp/FirmwareLoader.java | 7 +++---- .../spinnaker/alloc/bmp/MockTransceiver.java | 15 +++++++-------- .../transceiver/BMPWriteMemoryProcess.java | 4 ++-- .../transceiver/BMPWriteSerialFlashProcess.java | 4 ++-- .../manchester/spinnaker/transceiver/Utils.java | 3 +-- .../front_end/dse/FastDataInProtocol.java | 6 +++--- .../spinnaker/utils/ByteBufferUtils.java | 6 ++++-- .../spinnaker/utils/TestByteBufferUtils.java | 1 + .../spinnaker/utils/TestDefaultMap.java | 6 ++---- 9 files changed, 25 insertions(+), 27 deletions(-) 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 d8c8af5aeb..45617873fd 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 @@ -36,7 +36,6 @@ 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.UnitConstants.MSEC_PER_SEC; import java.io.FileNotFoundException; @@ -360,7 +359,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); } @@ -418,8 +417,8 @@ 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: 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 f98a1c6e8a..ce3deac0ff 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 @@ -23,8 +23,6 @@ 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 java.io.IOException; import java.io.InputStream; @@ -201,7 +199,7 @@ public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, length); // Pad to length - var b = slice(flash, baseAddress.address, length); + 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 +211,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 +225,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()); } @@ -252,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) { @@ -270,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 @@ -287,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-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java index cc6504decf..73e4e17510 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java @@ -18,9 +18,9 @@ import static java.lang.Math.min; import static java.nio.ByteBuffer.allocate; +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.utils.ByteBufferUtils.read; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice; import java.io.IOException; import java.io.InputStream; @@ -82,7 +82,7 @@ void writeMemory(BMPBoard board, MemoryLocation baseAddress, @Override ByteBuffer prepareSendBuffer(int chunkSize) { - var buffer = slice(data, offset, chunkSize); + var buffer = data.slice(offset, chunkSize).order(LITTLE_ENDIAN); offset += chunkSize; return buffer; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteSerialFlashProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteSerialFlashProcess.java index 70d57de7fa..60743c181d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteSerialFlashProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteSerialFlashProcess.java @@ -18,9 +18,9 @@ import static java.lang.Math.min; import static java.nio.ByteBuffer.allocate; +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.utils.ByteBufferUtils.read; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice; import java.io.IOException; import java.io.InputStream; @@ -82,7 +82,7 @@ void write(BMPBoard board, MemoryLocation baseAddress, ByteBuffer data) @Override ByteBuffer prepareSendBuffer(int chunkSize) { - var buffer = slice(data, offset, chunkSize); + var buffer = data.slice(offset, chunkSize).order(LITTLE_ENDIAN); offset += chunkSize; return buffer; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java index 58bdbc1935..534f7d1e84 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java @@ -20,7 +20,6 @@ import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_BYTES; import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.CPU_INFO; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice; import java.io.IOException; import java.net.InetAddress; @@ -160,7 +159,7 @@ static void fill(ByteBuffer buffer, int start, int len, byte value) { */ static int crc(ByteBuffer buffer, int start, int len) { var crc = new CRC32(); - crc.update(slice(buffer, start, len)); + crc.update(buffer.slice(start, len)); return (int) crc.getValue(); } } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java index e3ee03f306..91a93b0972 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java @@ -28,7 +28,6 @@ import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_NOT_EXPECTED; import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.slice; import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.nio.ByteBuffer; @@ -164,8 +163,9 @@ SDPMessage seqData(ByteBuffer data, int seqNum, int transactionId) { } private int putBuffer(ByteBuffer data, int position, ByteBuffer payload) { - var slice = slice(data, position, - min(data.remaining() - position, payload.remaining())); + var slice = data + .slice(position, + min(data.remaining() - position, payload.remaining())); payload.put(slice).flip(); return slice.position(); } diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java index 2a013edaf7..fc438a9219 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java @@ -40,10 +40,12 @@ private ByteBufferUtils() { * The length of the slice. * @return The little-endian slice. This will be read-only if and only if * the original buffer is read-only. + * @deprecated Replace with + * {@code src.slice(from, len).order(LITTLE_ENDIAN)} */ + @Deprecated(forRemoval = true) public static ByteBuffer slice(ByteBuffer src, int from, int len) { - var s = src.duplicate().position(from).slice(); - return s.limit(len).order(LITTLE_ENDIAN); + return src.slice(from, len).order(LITTLE_ENDIAN); } /** diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java index 2748a1a9aa..f7eb0e8aad 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java @@ -32,6 +32,7 @@ */ public class TestByteBufferUtils { @Test + @SuppressWarnings("removal") public void testSlice() { var bb = ByteBuffer.allocate(12).order(ByteOrder.LITTLE_ENDIAN); var s = ByteBufferUtils.slice(bb, 4, 4); diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestDefaultMap.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestDefaultMap.java index 06d522d827..c5bc64f372 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestDefaultMap.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestDefaultMap.java @@ -46,8 +46,7 @@ public void testUntyped() { @Test public void testTyped() { - // Explicit to work around weird issue in Java 14 compiler - Map> instance = new DefaultMap<>(ArrayList::new); + var instance = new DefaultMap>(ArrayList::new); var foo = instance.get("foo"); assertTrue(foo instanceof ArrayList); // foo.add("a"); @@ -79,8 +78,7 @@ public void testBad() { @Test public void testKeyAware() { - DefaultMap instance = - DefaultMap.newAdvancedDefaultMap(new Doubler()); + var instance = DefaultMap.newAdvancedDefaultMap(new Doubler()); var two = instance.get(1); assertEquals(2, two.intValue()); } From 17e28cbfee2084d90fe19c6d2b03786d0d2abfa4 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 29 Nov 2022 15:10:17 +0000 Subject: [PATCH 013/194] Starting to introduce records There are a few weird bugs in records still. Or maybe they're in Eclipse's incremental compiler. --- .../spinnaker/alloc/admin/UserControl.java | 35 ++-- .../spinnaker/alloc/allocator/Spalloc.java | 51 ++--- .../spinnaker/alloc/bmp/FirmwareLoader.java | 26 +-- .../manchester/spinnaker/alloc/bmp/Link.java | 35 +--- .../spinnaker/alloc/bmp/SpiNNaker1.java | 4 +- .../alloc/bmp/TransceiverFactory.java | 25 +-- .../alloc/compat/ExceptionResponse.java | 25 +-- .../alloc/compat/JobNotifyMessage.java | 26 +-- .../alloc/compat/MachineNotifyMessage.java | 26 +-- .../alloc/compat/ReturnResponse.java | 22 +- .../spinnaker/alloc/compat/Utils.java | 15 +- .../spinnaker/alloc/compat/V1TaskImpl.java | 3 +- .../spinnaker/alloc/model/BoardCoords.java | 168 +++------------ .../alloc/model/BoardIssueReport.java | 83 ++------ .../spinnaker/alloc/model/ConnectionInfo.java | 55 +---- .../spinnaker/alloc/model/DownLink.java | 40 ++-- .../spinnaker/alloc/model/JobDescription.java | 4 +- .../spinnaker/alloc/proxy/ProxyCore.java | 5 +- .../alloc/security/LocalAuthProviderImpl.java | 13 +- .../MyAuthenticationFailureHandler.java | 20 +- .../spinnaker/alloc/security/Token.java | 17 +- .../spinnaker/alloc/web/CreateJobRequest.java | 198 ++++++++---------- .../alloc/web/CreateJobResponse.java | 17 +- .../alloc/web/IssueReportRequest.java | 76 +++---- .../alloc/web/IssueReportResponse.java | 14 +- .../spinnaker/alloc/web/MachinePower.java | 24 +-- .../spinnaker/alloc/web/MachinesResponse.java | 80 +++---- .../web/SpallocServiceAPIImplBuilder.java | 2 +- .../alloc/web/SpallocServiceImpl.java | 102 +++++---- .../alloc/allocator/SpallocCoreTest.java | 12 +- .../spinnaker/alloc/web/JsonTest.java | 51 +++-- .../messages/bmp/ReadSerialVector.java | 5 +- .../front_end/dse/ExecutionContext.java | 33 +-- .../spinnaker/utils/OptionalUtils.java | 1 + 34 files changed, 446 insertions(+), 867 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java index 4dc0c1dff7..2031b2c905 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java @@ -594,20 +594,20 @@ 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). + * 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) */ - private static class GetUserResult { - final PasswordChangeRecord baseUser; - - final String oldEncPass; - - GetUserResult(Row row) { - baseUser = passChange(row); - oldEncPass = row.getString("encrypted_password"); + private static record GetUserResult(PasswordChangeRecord baseUser, + String oldEncPass) { + private GetUserResult(Row row) { + this(passChange(row), row.getString("encrypted_password")); } } @@ -623,7 +623,8 @@ 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) { @@ -638,7 +639,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"); } @@ -649,11 +650,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(); }); } 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 22071527b1..d384ee0b47 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 @@ -1028,24 +1028,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) { @@ -1290,13 +1290,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); @@ -1320,47 +1320,48 @@ private String reportIssue(IssueReportRequest report, Permit permit, private int getJobBoardForReport(BoardReportSQL q, ReportedBoard board, EmailBuilder email) throws ReportRollbackExn { Row r; - if (nonNull(board.chip)) { + if (nonNull(board.chip())) { r = q.findBoardByChip - .call1(id, root, board.chip.getX(), board.chip.getY()) - .orElseThrow(() -> new ReportRollbackExn(board.chip)); + .call1(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(machineId, board.x, board.y, board.z) + .call1(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())); var j = r.getInteger("job_id"); if (isNull(j) || id != j) { 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(machineId, board.cabinet, board.frame, - board.board) + .call1(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())); var j = r.getInteger("job_id"); if (isNull(j) || id != j) { 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(machineId, board.address) + } else if (nonNull(board.address())) { + r = q.findBoardNet.call1(machineId, board.address()) .orElseThrow(() -> new ReportRollbackExn( - "board at %s not in machine", board.address)); + "board at %s not in machine", board.address())); var j = r.getInteger("job_id"); if (isNull(j) || id != j) { throw new ReportRollbackExn( "board at %s not allocated to job %d", - board.address, id); + board.address(), id); } email.ip(board); } else { 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 45617873fd..2d58b929ad 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 @@ -298,14 +298,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 +315,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 +330,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); } } @@ -508,8 +504,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 6f7593d2d8..c1f61d1733 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,39 +23,14 @@ * 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 int board; - - /** Which link (and hence which FPGA). */ - private final Direction link; - - /** - * Create a request. - * - * @param board - * The DB ID of the board that the FPGA is located on. - * @param link - * Which link (and hence which FPGA). - */ - Link(int board, Direction link) { - this.board = board; - this.link = link; - } - +public record Link(int board, Direction link) { @Override public String toString() { return "Link(" + board + "," + link + ":OFF)"; } - - /** @return The database ID of the board that the FPGA is located on. */ - public int 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/SpiNNaker1.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java index f50ba934ac..f0f22eb25e 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 @@ -230,8 +230,8 @@ private boolean canBoardManageFPGAs(BMPBoard board) @Override public void setLinkOff(Link link) throws ProcessException, IOException, InterruptedException { - var board = requireNonNull(idToBoard.get(link.getBoard())); - var d = link.getLink(); + var board = requireNonNull(idToBoard.get(link.board())); + var d = link.link(); // skip FPGA link configuration if old BMP version if (!canBoardManageFPGAs(board)) { return; 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 8bff667357..700bc7d674 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 @@ -16,7 +16,6 @@ */ 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; @@ -69,29 +68,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 static record Key(String machine, BMPCoords bmp) { } @GuardedBy("itself") 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 fec7852dbe..6250847b24 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 @@ -16,31 +16,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 57dbe5bc97..3c5f84d55e 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 @@ -16,35 +16,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 c25c76b894..29badec0b7 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 @@ -16,35 +16,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 6a8fb70b5d..a906fe683d 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 @@ -16,30 +16,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/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.java index 682bc051f6..10661e1e6a 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 @@ -247,8 +247,7 @@ static State state(Job job) { * @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()); } /** @@ -259,13 +258,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/V1TaskImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java index fa5c41854f..8b15fa146d 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 @@ -160,8 +160,7 @@ protected final JobMachineInfo getJobMachineInfo(int jobId) return new JobMachineInfo(job.getWidth().orElse(0), job.getHeight().orElse(0), 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()); } 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 1d6f1ad47e..644dc45ebd 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 @@ -18,8 +18,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; @@ -35,73 +33,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. @@ -112,81 +67,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) { - return (o instanceof BoardCoords other) && (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); - } - - @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 e0fb4b905f..990c2799f7 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 @@ -21,6 +21,7 @@ import java.time.Instant; import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonCreator; import uk.ac.manchester.spinnaker.alloc.db.Row; import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; @@ -30,21 +31,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(int id, int boardId, String issue, String reporter, + String timestamp) { + this(id, boardId, issue, reporter, Instant.parse(timestamp)); } /** @@ -56,55 +60,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/ConnectionInfo.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/ConnectionInfo.java index e8b0df04cb..dec27e0e14 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 @@ -19,8 +19,6 @@ 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; @@ -29,7 +27,6 @@ import com.google.errorprone.annotations.Immutable; 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; @@ -38,10 +35,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) /* @@ -50,48 +49,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) { - return (other instanceof ConnectionInfo c) - && Objects.equals(chip, c.chip) - && Objects.equals(hostname, c.hostname); - } - - @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 3598b2e815..2f066555b5 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 @@ -28,33 +28,26 @@ * 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 static record End(@Valid BoardCoords board, + @NotNull Direction direction) { } /** @@ -71,15 +64,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/JobDescription.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JobDescription.java index 2594e5ce15..5c795aae37 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 @@ -286,7 +286,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; } @@ -297,7 +297,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/proxy/ProxyCore.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/proxy/ProxyCore.java index 7c5851220c..881371fe4b 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 @@ -104,11 +104,10 @@ public class ProxyCore implements AutoCloseable { this.localHost = localHost; for (var ci : connections) { try { - hosts.put(ci.getChip(), - InetAddress.getByName(ci.getHostname())); + hosts.put(ci.chip(), InetAddress.getByName(ci.hostname())); } catch (UnknownHostException e) { log.warn("unexpectedly unknown board address: {}", - ci.getHostname(), e); + ci.hostname(), e); } } recvFrom = Set.copyOf(hosts.values()); 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 2f95616ddd..cd1e7794d5 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 @@ -419,19 +419,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 static 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 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 08c36f2091..ff5e446ed0 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 @@ -65,25 +65,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; - } + static record AuthFailureObject(String message, Instant timestamp) { } } 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 e5d5d66b7c..800db97cd0 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 @@ -16,8 +16,6 @@ */ package uk.ac.manchester.spinnaker.alloc.security; -import java.io.Serializable; - import javax.servlet.http.HttpSession; import org.springframework.security.core.Authentication; @@ -27,17 +25,14 @@ * 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/web/CreateJobRequest.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/CreateJobRequest.java index 93adaf801c..ee68d5c60c 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 @@ -29,6 +29,7 @@ import javax.validation.constraints.Positive; import javax.validation.constraints.PositiveOrZero; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.errorprone.annotations.Keep; @@ -46,73 +47,65 @@ * 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). + * @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). - */ - public String group; - - /** - * 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(String owner, String group, + @NotNull(message = "keepalive-interval is " + + "required") Duration keepaliveInterval, + @Positive(message = "number of boards must be " + + "at least 1 if given") Integer numBoards, + @Valid Dimensions dimensions, @Valid SpecificBoard board, + String machineName, + List<@NotBlank(message = "tags must not be blank") String> tags, + @PositiveOrZero(message = "max-dead-boards may not be " + + "negative") Integer maxDeadBoards) { + @JsonCreator + CreateJobRequest(String owner, String group, + @NotNull(message = "keepalive-interval is " + + "required") String keepaliveInterval, + @Positive(message = "number of boards must be " + + "at least 1 if given") Integer numBoards, + @Valid Dimensions dimensions, @Valid SpecificBoard board, + String machineName, + List<@NotBlank(message = "tags must not be blank") String> tags, + @PositiveOrZero(message = "max-dead-boards may not be " + + "negative") Integer maxDeadBoards) { + this(owner, group, Duration.parse(keepaliveInterval), numBoards, + dimensions, board, machineName, tags, maxDeadBoards); + } // Extended validation @@ -164,47 +157,42 @@ 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 static 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 static 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 263b43fc03..68b857353f 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 @@ -31,18 +31,15 @@ * 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 a421546830..f5abb12bec 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 @@ -40,50 +40,40 @@ * 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 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 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 static record ReportedBoard(@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 21b5dfec77..586d18d1e2 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 @@ -22,16 +22,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/MachinePower.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinePower.java index bdc4e6df16..a76653c692 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 @@ -28,26 +28,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/MachinesResponse.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/MachinesResponse.java index acf50570fe..007796cf92 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 @@ -16,13 +16,12 @@ */ 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; @@ -35,59 +34,48 @@ * {@link BriefMachineDescription}s. * * @author Donal Fellows + * @param machines + * The list of machines known to the service. */ -public final class MachinesResponse { +public final 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 static 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/SpallocServiceAPIImplBuilder.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/SpallocServiceAPIImplBuilder.java index 67b16cff03..2ac1963fd9 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 @@ -230,7 +230,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 ee0e26a985..c66425b7cb 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 @@ -210,12 +210,13 @@ private static String trim(String str) { @Override public void createJob(CreateJobRequest req, UriInfo ui, SecurityContext security, AsyncResponse response) { - var crds = validateAndApplyDefaultsToJobRequest(req, security); + var r = validateCreateJobNonSizeAttrs(req, security); + var crds = validateAndApplyDefaultsToJobRequest(r, security); // Async because it involves getting a write lock bgAction(response, () -> ifElse( - core.createJob(trim(req.owner), trim(req.group), crds, - req.machineName, req.tags, req.keepaliveInterval, + core.createJob(trim(r.owner()), trim(r.group()), crds, + r.machineName(), r.tags(), r.keepaliveInterval(), mapper.writeValueAsBytes(req)), job -> created(ui.getRequestUriBuilder().path("{id}") .build(job.getId())) @@ -225,81 +226,90 @@ 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"); } - if (!security.isUserInRole("ADMIN") || isNull(req.owner) - || req.owner.isBlank()) { - req.owner = security.getUserPrincipal().getName(); + var owner = req.owner(); + if (!security.isUserInRole("ADMIN") || 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.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); - } 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/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 1f24bb06f8..e0bdf4f500 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 @@ -338,7 +338,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,12 +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.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(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/web/JsonTest.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/web/JsonTest.java index 2d804532eb..719439eddf 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 @@ -348,10 +348,10 @@ void testCreateJobRequestSimple() throws IOException { } """, 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 @@ -370,16 +370,37 @@ void testCreateJobRequestComplex() throws IOException { } """, 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 @@ -389,7 +410,7 @@ void testPowerRequest() throws IOException { "power": "ON" } """, MachinePower.class); - assertEquals(ON, mp.getPower()); + assertEquals(ON, mp.power()); } } } 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 b28227f596..76ba87379a 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 @@ -83,10 +83,7 @@ public int getHardwareVersion() { /** @return The serial number data, as a read-only buffer. */ public IntBuffer getSerialNumber() { - // TODO use slice(int,int) once base Java version recent enough - var b = buffer.asReadOnlyBuffer(); - b.position(SERIAL_INDEX).limit(SERIAL_INDEX + SERIAL_LENGTH); - return b.slice(); + return buffer.slice(SERIAL_INDEX, SERIAL_LENGTH).asReadOnlyBuffer(); } /** @return The location of the flash buffer. */ diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java index 9064c2559b..283e1b30b0 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java @@ -203,38 +203,15 @@ static class DanglingReferenceException } } - // Migrate to record in new enough Java @Immutable - private static class RegionToRef { - final CoreLocation core; - - final MemoryLocation pointer; - - RegionToRef(CoreLocation core, MemoryLocation pointer) { - this.core = core; - this.pointer = pointer; - } - - @Override - public String toString() { - return "RegionToRef(" + core + ", " + pointer + ")"; - } + private static record RegionToRef(CoreLocation core, + MemoryLocation pointer) { } - // Migrate to record in new enough Java - private static class CoreToFill { - final Executor executor; - - final MemoryLocation start; - - final CoreLocation core; - - final List refs = new ArrayList<>(); - + private static record CoreToFill(Executor executor, MemoryLocation start, + CoreLocation core, List refs) { CoreToFill(Executor executor, MemoryLocation start, CoreLocation core) { - this.executor = executor; - this.start = start; - this.core = core; + this(executor, start, core, new ArrayList<>()); } @Override diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/OptionalUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/OptionalUtils.java index 4cd3170d94..fe1dbf4625 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/OptionalUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/OptionalUtils.java @@ -72,6 +72,7 @@ public static Optional apply(Optional source, */ public static U ifElse(Optional source, Function ifPresent, Supplier ifAbsent) { + // Would use ifPresentOrElse, except that's void result return source.map(ifPresent).orElseGet(ifAbsent); } From 2b9cbab71c146c3a2fc46911ebee1495935787c7 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 30 Nov 2022 16:57:34 +0000 Subject: [PATCH 014/194] Records! Note that this is definitely the most intrusive of the changes as it alters the API of lots of basic model classes. --- .../spinnaker/alloc/ServiceVersion.java | 2 +- .../alloc/admin/MachineDefinitionLoader.java | 25 +- .../alloc/admin/MachineStateControl.java | 4 +- .../alloc/allocator/AllocatorTask.java | 24 +- .../spinnaker/alloc/allocator/Spalloc.java | 19 +- .../spinnaker/alloc/bmp/BMPController.java | 2 +- .../spinnaker/alloc/bmp/SpiNNaker1.java | 2 +- .../alloc/bmp/TransceiverFactory.java | 2 +- .../spinnaker/alloc/compat/V1TaskImpl.java | 3 +- .../spinnaker/alloc/db/SQLQueries.java | 6 +- .../spinnaker/alloc/SupportQueries.java | 2 +- .../spinnaker/alloc/bmp/MockTransceiver.java | 4 +- .../spinnaker/alloc/web/JsonTest.java | 2 +- .../spinnaker/alloc/client/CreateJob.java | 5 +- .../alloc/client/SpallocClientFactory.java | 4 +- .../spinnaker/connections/BMPConnection.java | 10 +- .../spinnaker/messages/bmp/BMPRequest.java | 4 +- .../spinnaker/messages/bmp/BMPSetLED.java | 2 +- .../spinnaker/messages/bmp/SetPower.java | 2 +- .../spinnaker/messages/model/AppID.java | 30 +- .../messages/model/BMPConnectionData.java | 110 ++-- .../spinnaker/messages/model/Blacklist.java | 14 +- .../messages/model/FirmwareDescriptor.java | 23 +- .../spinnaker/messages/model/HeapElement.java | 74 ++- .../messages/model/ReinjectionStatus.java | 148 ++---- .../messages/model/RouterTimeout.java | 22 +- .../spinnaker/messages/model/Version.java | 91 ++-- .../messages/scp/ApplicationRun.java | 2 +- .../messages/scp/ApplicationStop.java | 2 +- .../spinnaker/messages/scp/CountState.java | 2 +- .../messages/scp/FixedRouteInitialise.java | 2 +- .../messages/scp/FixedRouteRead.java | 2 +- .../spinnaker/messages/scp/FloodFillEnd.java | 2 +- .../spinnaker/messages/scp/RouterAlloc.java | 2 +- .../spinnaker/messages/scp/RouterInit.java | 2 +- .../spinnaker/messages/scp/SDRAMAlloc.java | 2 +- .../spinnaker/messages/scp/SDRAMDeAlloc.java | 2 +- .../spinnaker/messages/scp/SendSignal.java | 2 +- .../spinnaker/spalloc/SpallocClient.java | 2 +- .../spinnaker/spalloc/SpallocJob.java | 6 +- .../spalloc/messages/BoardCoordinates.java | 74 +-- .../spinnaker/spalloc/messages/BoardLink.java | 73 +-- .../messages/BoardPhysicalCoordinates.java | 82 +-- .../spalloc/messages/Connection.java | 48 +- .../messages/GetBoardAtPositionCommand.java | 6 +- .../messages/GetBoardPositionCommand.java | 6 +- .../spinnaker/spalloc/messages/WhereIs.java | 145 +---- .../WhereIsMachineBoardLogicalCommand.java | 6 +- .../WhereIsMachineBoardPhysicalCommand.java | 6 +- .../spinnaker/transceiver/AppIdTracker.java | 2 +- .../spinnaker/transceiver/GetHeapProcess.java | 42 +- .../spinnaker/transceiver/Transceiver.java | 52 +- .../transceiver/TransceiverInterface.java | 22 +- .../spinnaker/messages/model/TestVersion.java | 32 +- .../spinnaker/spalloc/SupportUtils.java | 7 + .../spinnaker/spalloc/TestClient.java | 498 +++++++++++++----- .../manchester/spinnaker/spalloc/TestJob.java | 96 ++-- .../spinnaker/spalloc/TestMockClient.java | 16 +- .../messages/TestBoardCoordinates.java | 6 +- .../TestBoardPhysicalCoordinates.java | 6 +- .../spalloc/messages/TestConnection.java | 8 +- .../spalloc/messages/TestMachine.java | 4 +- .../spalloc/messages/TestWhereIs.java | 42 +- .../front_end/download/DataGatherer.java | 37 +- .../front_end/download/DataReceiver.java | 4 +- .../download/DirectDataGatherer.java | 8 +- .../front_end/download/RecordingRegion.java | 2 +- .../front_end/download/request/Placement.java | 59 +-- .../front_end/download/request/Vertex.java | 102 +--- .../front_end/download/TestPlacements.java | 3 +- .../spinnaker/machine/board/BMPBoard.java | 23 +- .../spinnaker/machine/board/BMPCoords.java | 69 +-- .../machine/board/PhysicalCoords.java | 64 +-- .../spinnaker/machine/board/TriadCoords.java | 64 +-- .../machine/datalinks/InetIdTuple.java | 36 +- .../spinnaker/utils/CollectionUtils.java | 28 +- 76 files changed, 1020 insertions(+), 1424 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceVersion.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceVersion.java index 9d02cd74a5..9e1107ba69 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceVersion.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceVersion.java @@ -46,7 +46,7 @@ public class ServiceVersion { public ServiceVersion(@Value("${version}") String version, @Value("${build-timestamp}") String buildTimestamp) { fullVersion = version; - v = new Version(version.replaceAll("-.*", "")); + v = Version.parse(version.replaceAll("-.*", "")); this.buildTimestamp = buildTimestamp; } diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 1102aa44db..4839ee26d2 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -246,8 +246,9 @@ private static boolean badName(String name) { @JsonIgnore @AssertTrue(message = "all boards must have sane logical coordinates") private boolean isCoordinateSane() { - return boardLocations.keySet().stream().allMatch(loc -> (loc.x >= 0) - && (loc.x < width) && (loc.y >= 0) && (loc.y < height)); + return boardLocations.keySet().stream() + .allMatch(loc -> (loc.x() >= 0) && (loc.x() < width) + && (loc.y() >= 0) && (loc.y() < height)); } @Keep @@ -317,9 +318,9 @@ private static int limit(int value, int limit) { * @return The new location */ private TriadCoords move(TriadCoords here, Direction direction) { - var di = DirInfo.get(here.z, direction); - return new TriadCoords(limit(here.x + di.dx, width), - limit(here.y + di.dy, height), here.z + di.dz); + var di = DirInfo.get(here.z(), direction); + return new TriadCoords(limit(here.x() + di.dx, width), + limit(here.y() + di.dy, height), here.z() + di.dz); } @JsonPOJOBuilder @@ -723,7 +724,7 @@ private Map makeBMPs(Updates sql, Machine machine, int machineId) { var bmpIds = new HashMap(); machine.bmpIPs.forEach((bmp, ip) -> sql.makeBMP - .key(machineId, ip, bmp.cabinet, bmp.frame) + .key(machineId, ip, bmp.cabinet(), bmp.frame()) .ifPresent(id -> bmpIds.put(bmp, id))); return bmpIds; } @@ -741,12 +742,12 @@ private Map makeBoards(Updates sql, Machine machine, machine.deadBoards.contains(triad) ? "dead" : "live", triad); sql.makeBoard - .key(machineId, addr, bmpID, phys.b, triad.x, triad.y, - triad.z, root.getX(), root.getY(), + .key(machineId, addr, bmpID, phys.b(), triad.x(), triad.y(), + triad.z(), root.getX(), root.getY(), !machine.deadBoards.contains(triad)) .ifPresent(id -> boardIds.put(triad, id)); - maxX = max(maxX, triad.x * TRIAD_CHIP_SIZE); - maxY = max(maxY, triad.y * TRIAD_CHIP_SIZE); + maxX = max(maxX, triad.x() * TRIAD_CHIP_SIZE); + maxY = max(maxY, triad.y() * TRIAD_CHIP_SIZE); } /* * Note that even in single-board setups, the max coordinates are as if @@ -763,8 +764,8 @@ private Map makeBoards(Updates sql, Machine machine, var root = triad.asChipLocation(); log.debug("making {} board {}", "dead", triad); sql.makeBoard - .key(machineId, null, bmpID, null, triad.x, triad.y, - triad.z, root.getX(), root.getY(), false) + .key(machineId, null, bmpID, null, triad.x(), triad.y(), + triad.z(), root.getX(), root.getY(), false) .ifPresent(id -> boardIds.put(triad, id)); } return boardIds; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index b724ab2c0c..18f7c04c01 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -307,7 +307,7 @@ public Optional findTriad(@NotBlank String machine, @Valid @NonNull TriadCoords coords) { return executeRead(conn -> { try (var q = conn.query(FIND_BOARD_BY_NAME_AND_XYZ)) { - return q.call1(machine, coords.x, coords.y, coords.z) + return q.call1(machine, coords.x(), coords.y(), coords.z()) .map(BoardState::new); } }); @@ -326,7 +326,7 @@ public Optional findPhysical(@NotBlank String machine, @Valid @NotNull PhysicalCoords coords) { return executeRead(conn -> { try (var q = conn.query(FIND_BOARD_BY_NAME_AND_CFB)) { - return q.call1(machine, coords.c, coords.f, coords.b) + return q.call1(machine, coords.c(), coords.f(), coords.b()) .map(BoardState::new); } }); 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 806dd7dc0b..a3a1e0bf2f 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 @@ -115,20 +115,9 @@ public class AllocatorTask extends DatabaseAwareBean * * @author Donal Fellows */ - 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 static final record Rectangle(int width, int height, + /** Depth of rectangle. 1 or 3 */ + int depth) { private Rectangle(Row row) { this(row.getInt("max_width"), row.getInt("max_height"), TRIAD_DEPTH); @@ -756,7 +745,7 @@ private boolean allocateDimensions(AllocSQL sql, int jobId, int machineId, private int connectedSize(AllocSQL sql, int machineId, TriadCoords root, int width, int height) { return sql.countConnectedBoards - .call1(machineId, root.x, root.y, width, height) + .call1(machineId, root.x(), root.y(), width, height) .map(integer("connected_size")).orElse(-1); } @@ -848,9 +837,10 @@ private boolean allocateTriadsAt(AllocSQL sql, int jobId, int machineId, private boolean 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); + rect.width, rect.height, rect.depth, root.x(), root.y(), + root.z()); var boardsToAllocate = sql.getConnectedBoardIDs - .call(machineId, root.x, root.y, root.z, rect.width, + .call(machineId, root.x(), root.y(), root.z(), rect.width, rect.height, rect.depth) .map(integer("board_id")).toList(); if (boardsToAllocate.isEmpty()) { 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 d384ee0b47..cc79402039 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 @@ -558,15 +558,16 @@ private Integer locateBoard(Connection conn, String machineName, var findIP = conn.query(FIND_BOARD_BY_NAME_AND_IP_ADDRESS)) { if (nonNull(b.triad)) { return findTriad - .call1(machineName, b.triad.x, b.triad.y, b.triad.z) + .call1(machineName, b.triad.x(), b.triad.y(), + b.triad.z()) .filter(r -> !requireTriadRoot || r.getInt("z") == 0) .map(integer("board_id")) .orElseThrow(() -> new IllegalArgumentException( NO_BOARD_MSG)); } else if (nonNull(b.physical)) { return findPhysical - .call1(machineName, b.physical.c, - b.physical.f, b.physical.b) + .call1(machineName, b.physical.c(), + b.physical.f(), b.physical.b()) .filter(r -> !requireTriadRoot || r.getInt("z") == 0) .map(integer("board_id")) .orElseThrow(() -> new IllegalArgumentException( @@ -769,7 +770,8 @@ public Optional getBoardByPhysicalCoords( try (var conn = getConnection(); var findBoard = conn.query(findBoardByPhysicalCoords)) { return conn.transaction(false, - () -> findBoard.call1(id, coords.c, coords.f, coords.b) + () -> findBoard + .call1(id, coords.c(), coords.f(), coords.b()) .map(row -> new BoardLocationImpl(row, this))); } } @@ -780,7 +782,8 @@ public Optional getBoardByLogicalCoords( try (var conn = getConnection(); var findBoard = conn.query(findBoardByLogicalCoords)) { return conn.transaction(false, - () -> findBoard.call1(id, coords.x, coords.y, coords.z) + () -> findBoard + .call1(id, coords.x(), coords.y(), coords.z()) .map(row -> new BoardLocationImpl(row, this))); } } @@ -900,8 +903,7 @@ public String getBMPAddress(BMPCoords bmp) { try (var conn = getConnection(); var bmpAddr = conn.query(GET_BMP_ADDRESS)) { return conn.transaction(false, - () -> bmpAddr - .call1(id, bmp.getCabinet(), bmp.getFrame()) + () -> bmpAddr.call1(id, bmp.cabinet(), bmp.frame()) .map(string("address")).orElse(null)); } } @@ -911,8 +913,7 @@ public List getBoardNumbers(BMPCoords bmp) { try (var conn = getConnection(); var boardNumbers = conn.query(GET_BMP_BOARD_NUMBERS)) { return conn.transaction(false, - () -> boardNumbers - .call(id, bmp.getCabinet(), bmp.getFrame()) + () -> boardNumbers.call(id, bmp.cabinet(), bmp.frame()) .map(integer("board_num")).toList()); } } 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 c3fd30cd53..805f295856 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 @@ -765,7 +765,7 @@ private boolean badBoard(ProcessException failure, AfterSQL sql) { private Optional getBoardId(HasCoreLocation addr) { return idToBoard.get(new BMPCoords(addr.getX(), addr.getY())) .entrySet().stream() - .filter(ib2 -> ib2.getValue().board == addr.getP()) + .filter(ib2 -> ib2.getValue().board() == addr.getP()) .map(Entry::getKey).findFirst(); } } 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 f0f22eb25e..dc613b1928 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 @@ -218,7 +218,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; } /** 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 700bc7d674..21afdd1d0f 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 @@ -191,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/V1TaskImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/V1TaskImpl.java index 8b15fa146d..0e91deb404 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 @@ -252,7 +252,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) 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 b43c8dd05d..9c79c4495f 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 @@ -2108,7 +2108,7 @@ JOIN board_model_coords USING (coord_id) @Parameter("x") @Parameter("y") protected static final String ADD_BLACKLISTED_CHIP = """ - WITH args(board_id, x, y) AS (VALUES(:board_id, :x, :y))," + WITH args(board_id, x, y) AS (VALUES(:board_id, :x, :y)), m(model) AS (SELECT board_model FROM machines JOIN boards USING (machine_id) JOIN args USING (board_id)) @@ -2286,7 +2286,7 @@ LEFT JOIN board_serial USING (board_id) @Parameter("physical_serial_id") @GeneratesID protected static final String SET_BOARD_SERIAL_IDS = """ - INSERT INTO board_serial(" + INSERT INTO board_serial( board_id, bmp_serial_id, physical_serial_id) VALUES (:board_id, :bmp_serial_id, :physical_serial_id) ON CONFLICT DO UPDATE @@ -2383,7 +2383,7 @@ INSERT INTO board_serial(" @GeneratesID protected static final String CREATE_BLACKLIST_READ = """ INSERT INTO blacklist_ops( - board_id, op, completed) " + board_id, op, completed) VALUES (:board_id, 0, 0) """; 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 e03bfa9a9a..b19929e774 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 @@ -47,7 +47,7 @@ INSERT INTO job_request( String TEST_INSERT_REQ_DIMS = """ INSERT INTO job_request( job_id, width, height, max_dead_boards) - VALUES (?, ?, ?, ?)" + VALUES (?, ?, ?, ?) """; /** Insert a request-for-a-board. */ 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 ce3deac0ff..b2f691f49f 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 @@ -99,7 +99,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; @@ -140,7 +140,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); } } 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 719439eddf..ad1edb5442 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 @@ -225,7 +225,7 @@ class Serialization { @Test void testServiceDescription() throws IOException, JSONException { var d = new ServiceDescription(); - d.setVersion(new Version("1.2.3")); + d.setVersion(Version.parse("1.2.3")); JSONAssert.assertEquals(""" { "version": { 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 8d39092023..d18bc21174 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 @@ -295,7 +295,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; } @@ -311,7 +311,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/SpallocClientFactory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClientFactory.java index 94b322bebc..cacd40db5c 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 @@ -743,14 +743,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 5d7d136037..2c34b45f0f 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 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 be037e8202..3c6fdf058b 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 @@ -44,12 +44,12 @@ private static SDPHeader bmpHeader(int board) { } private static SDPHeader bmpHeader(BMPBoard board) { - return bmpHeader(board.board); + return bmpHeader(board.board()); } private static SDPHeader bmpHeader(Collection boards) { return bmpHeader( - boards.stream().mapToInt(b -> b.board).min().orElse(0)); + boards.stream().mapToInt(b -> b.board()).min().orElse(0)); } /** 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/BMPSetLED.java index 9fbe28d480..3874337b5f 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/BMPSetLED.java @@ -48,7 +48,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 d33c80e5dc..bc78c81ebf 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 @@ -58,7 +58,7 @@ private static int argument1(double delay, PowerCommand powerCommand) { } 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/model/AppID.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java index 0e55b10189..60ec7bd58f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/AppID.java @@ -21,8 +21,10 @@ * owners. * * @author Donal Fellows + * @param appID + * The proposed ID of the application. Must be between 0 and 255. */ -public final class AppID { +public record AppID(int appID) { /** * Maximum app ID. */ @@ -33,35 +35,11 @@ public final class AppID { */ public static final AppID DEFAULT = new AppID(0); - /** - * The application ID. - */ - public final int appID; - - /** - * Create an application ID. - * - * @param appID - * The proposed ID of the application. Must be between 0 and 255. - * @throws IllegalArgumentException - * If an illegal ID is given. - */ - public AppID(int appID) { + public AppID { if (appID < 0 || appID > MAX_APP_ID) { throw new IllegalArgumentException( "appID must be between 0 and " + MAX_APP_ID); } - this.appID = appID; - } - - @Override - public boolean equals(Object o) { - return (o instanceof AppID other) && (appID == other.appID); - } - - @Override - public int hashCode() { - return (appID << 5) ^ 1236984681; } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java index 2f865ee08a..2f378872b0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java @@ -37,59 +37,54 @@ /** * Contains the details of a connection to a SpiNNaker Board Management * Processor (BMP). + * + * @param boards + * The boards to be addressed. + * @param bmp + * The coordinates of the BMP that manages a set of boards. + * @param ipAddress + * The IP address of the BMP. + * @param portNumber + * The port number associated with the BMP connection, or + * {@code null} for the default. */ -public class BMPConnectionData { - /** The boards to be addressed. Unmodifiable. */ - public final Collection<@Valid BMPBoard> boards; - - /** The coordinates of the BMP that manages a set of boards. */ - @Valid - public final BMPCoords bmp; - - /** The IP address of the BMP. */ - @IPAddress - public final InetAddress ipAddress; - +public record BMPConnectionData(Collection<@Valid BMPBoard> boards, + @Valid BMPCoords bmp, @IPAddress InetAddress ipAddress, + @UDPPort Integer portNumber) { /** - * The port number associated with the BMP connection, or {@code null} for - * the default. - */ - @UDPPort - public final Integer portNumber; - - /** - * @param cabinet The number of the cabinet containing the frame. - * @param frame The number of the frame containing the boards. - * @param ipAddress The address of the BMP. - * @param boards The boards controlled by the BMP. - * @param portNumber The BMP's port. + * @param cabinet + * The number of the cabinet containing the frame. + * @param frame + * The number of the frame containing the boards. + * @param ipAddress + * The address of the BMP. + * @param boards + * The boards controlled by the BMP. + * @param portNumber + * The BMP's port. */ public BMPConnectionData(int cabinet, int frame, InetAddress ipAddress, Collection boards, Integer portNumber) { - this.bmp = new BMPCoords(cabinet, frame); - this.ipAddress = ipAddress; - this.boards = boards.stream().map(BMPBoard::new) - .collect(toUnmodifiableList()); - this.portNumber = portNumber; + this(boards.stream().map(BMPBoard::new).collect(toUnmodifiableList()), + new BMPCoords(cabinet, frame), ipAddress, portNumber); } /** - * @param coords The coordinates of the BMP. - * @param ipAddress The address of the BMP. - * @param boards The boards controlled by the BMP. - * @param portNumber The BMP's port. + * @param coords + * The coordinates of the BMP. + * @param ipAddress + * The address of the BMP. + * @param boards + * The boards controlled by the BMP. + * @param portNumber + * The BMP's port. */ public BMPConnectionData(BMPCoords coords, InetAddress ipAddress, Collection boards, Integer portNumber) { - this.bmp = coords; - this.ipAddress = ipAddress; - this.boards = boards.stream().map(BMPBoard::new) - .collect(toUnmodifiableList()); - this.portNumber = portNumber; + this(boards.stream().map(BMPBoard::new).collect(toUnmodifiableList()), + coords, ipAddress, portNumber); } - private static final int MIN_BYTE_FIELD = 3; - /** * Work out the BMP connection IP address given the machine details. This is * assumed to be the IP address of the machine, with 1 subtracted from the @@ -113,6 +108,18 @@ public BMPConnectionData(BMPCoords coords, InetAddress ipAddress, */ public BMPConnectionData(InetAddress host, int numBoards) throws UnknownHostException { + /* + * Assumes a single board (or small group) with no cabinet or frame + * specified + */ + this(makeBoards(numBoards), new BMPCoords(0, 0), guessBMPIP(host), + SCP_SCAMP_PORT); + } + + private static final int MIN_BYTE_FIELD = 3; + + private static InetAddress guessBMPIP(InetAddress host) + throws UnknownHostException { // take the IP address, split by dots, and subtract 1 off last bit var ipBits = host.getAddress(); if (ipBits[MIN_BYTE_FIELD] == 0 || ipBits[MIN_BYTE_FIELD] == 1) { @@ -121,19 +128,16 @@ public BMPConnectionData(InetAddress host, int numBoards) "BMP address would have illegal IP address"); } ipBits[MIN_BYTE_FIELD]--; - ipAddress = getByAddress(ipBits); - portNumber = SCP_SCAMP_PORT; - - // Assume a single board with no cabinet or frame specified - bmp = new BMPCoords(0, 0); + return getByAddress(ipBits); + } - // add board scope for each split - // if null, the end user didn't enter anything, so assume one board - // starting at position 0 - if (numBoards == 0) { - boards = List.of(new BMPBoard(0)); + private static List makeBoards(int numBoards) { + // if 0 or crazy, the end user didn't enter anything useful, so + // assume one board starting at position 0 + if (numBoards < 1) { + return List.of(new BMPBoard(0)); } else { - boards = range(0, numBoards).mapToObj(BMPBoard::new) + return range(0, numBoards).mapToObj(BMPBoard::new) .collect(toUnmodifiableList()); } } @@ -141,9 +145,9 @@ public BMPConnectionData(InetAddress host, int numBoards) @Override public String toString() { return format( - "(c:%d,f:%d,b:%s; %s)", bmp.cabinet, bmp.frame, + "(c:%d,f:%d,b:%s; %s)", bmp.cabinet(), bmp.frame(), boards.stream().findFirst() - .map(board -> board.board + "...").orElse(""), + .map(board -> board.board() + "...").orElse(""), ipAddress); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index 103e86c79b..49b2f3b411 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -28,6 +28,7 @@ import static java.util.regex.Pattern.compile; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; +import static java.util.stream.Collectors.toUnmodifiableSet; import static java.util.stream.IntStream.range; import static org.apache.commons.io.IOUtils.buffer; import static org.slf4j.LoggerFactory.getLogger; @@ -70,7 +71,6 @@ import uk.ac.manchester.spinnaker.machine.Direction; import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; import uk.ac.manchester.spinnaker.machine.ValidP; -import uk.ac.manchester.spinnaker.utils.CollectionUtils; import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; /** @@ -305,13 +305,14 @@ private static String deleteMatched(Matcher m) { return sb.toString(); } - private static Set parseCommaSeparatedSet(String str) { - return CollectionUtils.parseCommaSeparatedSet(str, Integer::parseInt); + private static Set parseCommaSeparatedSet(String str, + Function mapper) { + return stream(str.split(",")).map(mapper).collect(toUnmodifiableSet()); } private static > Set parseCommaSeparatedSet( - String str, Function fun, Class cls) { - return stream(str.split(",")).map(Integer::parseInt).map(fun) + String str, Function mapper, Class cls) { + return stream(str.split(",")).map(Integer::parseInt).map(mapper) .collect(toEnumSet(cls)); } @@ -346,7 +347,8 @@ private void parseLine(String line) { while (true) { m = CORE_PATTERN.matcher(rest); if (m.find() && deadCores == null) { - deadCores = parseCommaSeparatedSet(m.group("cores")); + deadCores = parseCommaSeparatedSet( + m.group("cores"), Integer::parseInt); deadCores.forEach(c -> { if (c < 0 || c >= PROCESSORS_PER_CHIP) { throw new IllegalArgumentException( diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/FirmwareDescriptor.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/FirmwareDescriptor.java index 5f764af448..3a1ade6d41 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/FirmwareDescriptor.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/FirmwareDescriptor.java @@ -20,8 +20,16 @@ import java.nio.IntBuffer; import java.time.Instant; -/** A firmware descriptor. */ -public class FirmwareDescriptor { +/** + * A firmware descriptor. + * + * @param type + * What type of firmware is this. + * @param descriptorData + * The descriptor buffer. Should be read-only. + */ +public record FirmwareDescriptor(FirmwareDescriptors type, + IntBuffer descriptorData) { private static final int MAX_OLD_STYLE = 65535; private static final int OLD_SPLIT = 100; @@ -30,10 +38,6 @@ public class FirmwareDescriptor { private static final int BYTE_SHIFT = 8; - private final FirmwareDescriptors type; - - private final IntBuffer descriptorData; - /** * Create a description of some firmware on a SpiNNaker system. * @@ -43,12 +47,11 @@ public class FirmwareDescriptor { * What was the descriptor buffer read from the system? */ public FirmwareDescriptor(FirmwareDescriptors type, ByteBuffer buffer) { - this.type = type; - descriptorData = buffer.asIntBuffer().asReadOnlyBuffer(); + this(type, buffer.asIntBuffer().asReadOnlyBuffer()); } /** @return The version of the firmware. */ - public Version getVersion() { + public Version version() { int n = descriptorData.get(type.versionIndex); if (n <= MAX_OLD_STYLE) { @@ -66,7 +69,7 @@ public Version getVersion() { } /** @return The timestamp in the firmware. */ - public Instant getTimestamp() { + public Instant timestamp() { return Instant.ofEpochSecond(descriptorData.get(type.timestampIndex)); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/HeapElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/HeapElement.java index d945039768..04af391cb4 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/HeapElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/HeapElement.java @@ -18,35 +18,30 @@ import uk.ac.manchester.spinnaker.machine.MemoryLocation; -/** An element of one of the heaps on SpiNNaker. */ +/** + * An element of one of the heaps on SpiNNaker. + * + * @param blockAddress + * The address of the block. + * @param nextAddress + * A pointer to the next block, or {@link MemoryLocation#NULL} if + * none. + * @param size + * The usable size of this block (not including the header). + * @param isFree + * True if the block is free. + * @param tag + * The tag of the block if allocated, or {@code null} if not. + * @param appID + * The application ID of the block if allocated, or {@code null} if + * not. + */ @SARKStruct("block") -public class HeapElement { - /** The address of the block. */ - public final MemoryLocation blockAddress; - - /** A pointer to the next block, or 0 if none. */ - @SARKField("next") - public final MemoryLocation nextAddress; - - /** The usable size of this block (not including the header). */ - public final int size; - - // Note that multiple fields are encoded in the free field. - - /** True if the block is free. */ - @SARKField("free") - public final boolean isFree; - - /** The tag of the block if allocated, or {@code null} if not. */ - @SARKField("free") - public final Integer tag; - - /** - * The application ID of the block if allocated, or {@code null} if not. - */ - @SARKField("free") - public final AppID appID; - +public record HeapElement(MemoryLocation blockAddress, + @SARKField("next") MemoryLocation nextAddress, int size, + // Note that multiple fields are encoded in the free field. + @SARKField("free") boolean isFree, @SARKField("free") Integer tag, + @SARKField("free") AppID appID) { private static final int FREE_MASK = 0xFFFF0000; private static final int BYTE_MASK = 0x000000FF; @@ -66,17 +61,16 @@ public class HeapElement { */ public HeapElement(MemoryLocation blockAddress, MemoryLocation nextAddress, int free) { - this.blockAddress = blockAddress; - this.nextAddress = nextAddress; - this.isFree = (free & FREE_MASK) != FREE_MASK; - if (isFree) { - tag = null; - appID = null; - } else { - tag = free & BYTE_MASK; - appID = new AppID((free >>> BYTE1_SHIFT) & BYTE_MASK); - } - size = nextAddress.diff(blockAddress) - BLOCK_HEADER_SIZE; + // Chain via another constructor so we have convenient access to isFree + this(blockAddress, nextAddress, free, (free & FREE_MASK) != FREE_MASK); + } + + private HeapElement(MemoryLocation blockAddress, MemoryLocation nextAddress, + int free, boolean isFree) { + this(blockAddress, nextAddress, + nextAddress.diff(blockAddress) - BLOCK_HEADER_SIZE, isFree, + isFree ? null : free & BYTE_MASK, + isFree ? null : new AppID((free >>> BYTE1_SHIFT) & BYTE_MASK)); } /** @@ -85,7 +79,7 @@ public HeapElement(MemoryLocation blockAddress, MemoryLocation nextAddress, * @return The address of the data ({@link #size} bytes long) that * immediately follows the heap element header. */ - public final MemoryLocation getDataAddress() { + public final MemoryLocation dataAddress() { return blockAddress.add(BLOCK_HEADER_SIZE); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ReinjectionStatus.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ReinjectionStatus.java index 8a78a9ab49..66bf1961d1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ReinjectionStatus.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ReinjectionStatus.java @@ -21,8 +21,37 @@ /** * Represents a status information message obtained from the dropped packet * reinjection core (an "extra monitor" core). + * + * @param timeout + * The WAIT1 timeout value of the router in cycles. + * @param emergencyTimeout + * The WAIT2 timeout value of the router in cycles. + * @param droppedPackets + * The number of packets dropped by the router and received by the + * reinjection functionality (may not fit in the queue though). + * @param missedDroppedPackets + * The number of times that when a dropped packet was read it was + * found that another one or more packets had also been dropped, but + * had been missed. + * @param droppedPacketOverflows + * Of the {@link #droppedPackets} received, how many were lost due to + * not having enough space in the queue of packets to reinject. + * @param reinjectedPackets + * Of the {@link #droppedPackets} received, how many packets were + * successfully reinjected. + * @param linkDumps + * The number of times that when a dropped packet was caused due to a + * link failing to take the packet. + * @param processorDumps + * The number of times that when a dropped packet was caused due to a + * processor failing to take the packet. + * @param flags + * The flags that states which types of packets were being recorded. */ -public class ReinjectionStatus { +public record ReinjectionStatus(RouterTimeout timeout, + RouterTimeout emergencyTimeout, int droppedPackets, + int missedDroppedPackets, int droppedPacketOverflows, + int reinjectedPackets, int linkDumps, int processorDumps, int flags) { /** Used to pick low nybble of value. */ static final int MASK = 0xF; @@ -43,124 +72,15 @@ public static int encodeTimeout(int mantissa, int exponent) { return (mantissa & MASK) | ((exponent & MASK) << SHIFT); } - /** The WAIT1 timeout value of the router in cycles. */ - private final RouterTimeout timeout; - - /** The WAIT2 timeout value of the router in cycles. */ - private final RouterTimeout emergencyTimeout; - - /** - * The number of packets dropped by the router and received by the - * reinjection functionality (may not fit in the queue though). - */ - private final int droppedPackets; - - /** - * The number of times that when a dropped packet was read it was found that - * another one or more packets had also been dropped, but had been missed. - */ - private final int missedDroppedPackets; - - /** - * Of the {@link #droppedPackets} received, how many were lost due to not - * having enough space in the queue of packets to reinject. - */ - private final int droppedPacketOverflows; - - /** - * Of the {@link #droppedPackets} received, how many packets were - * successfully reinjected. - */ - private final int reinjectedPackets; - - /** - * The number of times that when a dropped packet was caused due to a link - * failing to take the packet. - */ - private final int linkDumps; - - /** - * The number of times that when a dropped packet was caused due to a - * processor failing to take the packet. - */ - private final int processorDumps; - - /** The flags that states which types of packets were being recorded. */ - private final int flags; - /** * @param buffer * The message containing the status to parse. */ public ReinjectionStatus(ByteBuffer buffer) { - this.timeout = new RouterTimeout(buffer.getInt()); - this.emergencyTimeout = new RouterTimeout(buffer.getInt()); - this.droppedPackets = buffer.getInt(); - this.missedDroppedPackets = buffer.getInt(); - this.droppedPacketOverflows = buffer.getInt(); - this.reinjectedPackets = buffer.getInt(); - this.linkDumps = buffer.getInt(); - this.processorDumps = buffer.getInt(); - this.flags = buffer.getInt(); - } - - /** @return The WAIT1 timeout value of the router in cycles. */ - public RouterTimeout getTimeout() { - return timeout; - } - - /** @return The WAIT2 timeout value of the router in cycles. */ - public RouterTimeout getEmergencyTimeout() { - return emergencyTimeout; - } - - /** - * @return The number of packets dropped by the router and received by the - * reinjection functionality (may not fit in the queue though). - */ - public int getNumDroppedPackets() { - return droppedPackets; - } - - /** - * @return The number of times that when a dropped packet was read it was - * found that another one or more packets had also been dropped, but - * had been missed. - */ - public int getNumMissedDroppedPackets() { - return missedDroppedPackets; - } - - /** - * @return Of the n_dropped_packets received, how many were lost due to not - * having enough space in the queue of packets to reinject. - */ - public int getNumDroppedPacketOverflows() { - return droppedPacketOverflows; - } - - /** - * @return The number of times that when a dropped packet was caused due to - * a processor failing to take the packet. - */ - public int getNumProcessorDumps() { - return processorDumps; - } - - /** - * @return The number of times that when a dropped packet was caused due to - * a link failing to take the packet. - */ - public int getNumLinkDumps() { - return linkDumps; - } - - /** - * @return Of the number of dropped packets received, how many packets were - * successfully reinjected. - */ - public int getNumReinjectedPackets() { - return reinjectedPackets; + this(new RouterTimeout(buffer.getInt()), + new RouterTimeout(buffer.getInt()), buffer.getInt(), + buffer.getInt(), buffer.getInt(), buffer.getInt(), + buffer.getInt(), buffer.getInt(), buffer.getInt()); } private boolean flag(DPRIFlags flag) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterTimeout.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterTimeout.java index 558f2c7c6d..059e28220d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterTimeout.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterTimeout.java @@ -23,8 +23,12 @@ * A router timeout, originally stored as an 8-bit unsigned float. * * @author Donal Fellows + * @param mantissa + * The mantissa of the timeout. + * @param exponent + * The exponent of the timeout. */ -public final class RouterTimeout { +public record RouterTimeout(byte mantissa, byte exponent) { private static final int MANTISSA_OFFSET = 16; private static final int EXPONENT_OFFSET = 4; @@ -34,15 +38,8 @@ public final class RouterTimeout { private static final double CLOCK_INTERVAL = 1e9 / 133e6; - /** The mantissa of the timeout. */ - public final int mantissa; - - /** The exponent of the timeout. */ - public final int exponent; - RouterTimeout(int encodedValue) { - mantissa = encodedValue & MASK; - exponent = (encodedValue >> SHIFT) & MASK; + this(encodedValue, encodedValue >> SHIFT); } /** @@ -52,14 +49,13 @@ public final class RouterTimeout { * The exponent of the value; only low 4 bits used. */ public RouterTimeout(int mantissa, int exponent) { - this.mantissa = mantissa & MASK; - this.exponent = exponent & MASK; + this((byte) (mantissa & MASK), (byte) (exponent & MASK)); } /** * @return the timeout value of a router in ticks. */ - public int getValue() { + public int value() { int m = mantissa + MANTISSA_OFFSET; if (exponent <= EXPONENT_OFFSET) { return (m - (1 << (EXPONENT_OFFSET - exponent))) * (1 << exponent); @@ -72,6 +68,6 @@ public String toString() { if (mantissa == INF.mantissa && exponent == INF.exponent) { return "INF"; } - return "" + (getValue() * CLOCK_INTERVAL) + " ns"; + return "" + (value() * CLOCK_INTERVAL) + " ns"; } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java index 95cd8ec25b..b8e5618996 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java @@ -27,39 +27,28 @@ * A three-part semantic version description. * * @author Donal Fellows + * @param majorVersion + * The major version number. Two versions are not compatible if they + * have different major version numbers. Major version number + * differences dominate. The major version is supposed to only be + * updated when an incompatible API change occurs. + * @param minorVersion + * The minor version number. A version is compatible with another + * version if it has the same major version and a minor version that + * is greater than or equal to the other minor version. The minor + * version is supposed to be updated when a compatible API change + * occurs. + * @param revision + * The revision number. Less important than the minor version number. + * Two versions are usually compatible if they have the same major + * and minor version, with the revision being typically unimportant + * for that decision. Revisions should be updated when a new release + * happens, even if that only contains bug fixes and no API changes. */ -public final class Version implements Comparable { +public record Version(@JsonProperty("major-version") int majorVersion, + @JsonProperty("minor-version") int minorVersion, + @JsonProperty("revision") int revision) implements Comparable { // There is no standard Version class. WRYYYYYYYYYYYYYYYY!!!! - /** - * The major version number. Two versions are not compatible if they have - * different major version numbers. Major version number differences - * dominate. - */ - public final int majorVersion; - - /** The minor version number. */ - public final int minorVersion; - - /** The revision number. Less important than the minor version number. */ - public final int revision; - - /** - * Create a version number. - * - * @param major - * the major number - * @param minor - * the minor number - * @param rev - * the revision number - */ - public Version(@JsonProperty("major-version") int major, - @JsonProperty("minor-version") int minor, - @JsonProperty("revision") int rev) { - majorVersion = major; - minorVersion = minor; - revision = rev; - } /** * Create a version number. @@ -72,9 +61,7 @@ public Version(@JsonProperty("major-version") int major, * the revision number */ public Version(String major, String minor, String rev) { - majorVersion = parseInt(major); - minorVersion = parseInt(minor); - revision = parseInt(rev); + this(parseInt(major), parseInt(minor), parseInt(rev)); } // This RE is in Extended mode syntax, which COMMENTS enables @@ -96,15 +83,15 @@ public Version(String major, String minor, String rev) { * If the version string doesn't match one of the supported * patterns. */ - public Version(String threePartVersion) { + public static Version parse(String threePartVersion) { var m = VERSION_RE.matcher(threePartVersion); if (!m.matches()) { throw new IllegalArgumentException( "bad version string: " + threePartVersion); } - majorVersion = parseInt(m.group("major")); - minorVersion = parsePossibleInt(m.group("minor")); - revision = parsePossibleInt(m.group("revision")); + return new Version(parseInt(m.group("major")), + parsePossibleInt(m.group("minor")), + parsePossibleInt(m.group("revision"))); } private static int parsePossibleInt(String s) { @@ -114,17 +101,6 @@ private static int parsePossibleInt(String s) { return parseInt(s); } - @Override - public boolean equals(Object other) { - return (other instanceof Version v) && (majorVersion == v.majorVersion) - && (minorVersion == v.minorVersion) && (revision == v.revision); - } - - @Override - public int hashCode() { - return (majorVersion << 10) ^ (minorVersion << 5) ^ revision; - } - @Override public int compareTo(Version other) { int cmp = compare(majorVersion, other.majorVersion); @@ -139,6 +115,21 @@ public int compareTo(Version other) { @Override public String toString() { - return "" + majorVersion + "." + minorVersion + "." + revision; + return majorVersion + "." + minorVersion + "." + revision; + } + + /** + * Determine whether this version is compatible with the given requirement. + * For a version to match a requirement, it must have the same major version + * and a minor version/revision that is at least what the requirement + * states. + * + * @param requirement + * The version that we are testing for compatibility with. + * @return True if they are compatible, false otherwise. + */ + public boolean compatibleWith(Version requirement) { + return (majorVersion == requirement.majorVersion) + && compareTo(requirement) >= 0; } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java index 7cceffb2a9..1cd36698af 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java @@ -72,7 +72,7 @@ private static int argument1(AppID appId, Iterable processors, } } } - processorMask |= appId.appID << BYTE3; + processorMask |= appId.appID() << BYTE3; if (wait) { processorMask |= 1 << WAIT_BIT; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationStop.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationStop.java index 6af55ffc53..0defb22ad9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationStop.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationStop.java @@ -45,7 +45,7 @@ private static int argument1() { private static int argument2(AppID appID) { return (MAGIC2 << SHIFT) | (STOP.value << BYTE2) | (APP_MASK << BYTE1) - | (appID.appID << BYTE0); + | (appID.appID() << BYTE0); } private static int argument3() { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java index b8fddd1342..35e3b2e29d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java @@ -52,7 +52,7 @@ public CountState(AppID appID, CPUState state) { } private static int argument2(AppID appId, CPUState state) { - int data = (APP_MASK << BYTE1) | (appId.appID << BYTE0); + int data = (APP_MASK << BYTE1) | (appId.appID() << BYTE0); data |= COUNT_OPERATION << OP_SHIFT; data |= COUNT_MODE << MODE_SHIFT; data |= state.value << BYTE2; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteInitialise.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteInitialise.java index 50b20b8f6f..101fc98619 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteInitialise.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteInitialise.java @@ -27,7 +27,7 @@ /** Sets a fixed route entry. */ public final class FixedRouteInitialise extends SCPRequest { private static int argument1(AppID appID) { - return appID.appID << BYTE1; + return appID.appID() << BYTE1; } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteRead.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteRead.java index b2098730ec..043a9236cf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteRead.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FixedRouteRead.java @@ -33,7 +33,7 @@ public final class FixedRouteRead extends SCPRequest { private static final int MAGIC = 3; private static int argument1(AppID appID) { - return (appID.appID << BYTE1) | (MAGIC << BYTE0); + return (appID.appID() << BYTE1) | (MAGIC << BYTE0); } private static int argument2() { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillEnd.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillEnd.java index 546168dca6..978fa8003f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillEnd.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillEnd.java @@ -97,7 +97,7 @@ private static int argument2(AppID appID, Iterable processors, } } } - processorMask |= appID.appID << BYTE3; + processorMask |= appID.appID() << BYTE3; if (wait) { processorMask |= 1 << WAIT_BIT; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java index fc8cb3408d..76393c17e6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java @@ -47,7 +47,7 @@ public RouterAlloc(HasChipLocation chip, AppID appID, int numEntries) { } private static int argument1(AppID appID) { - return (appID.appID << BYTE1) | (ALLOC_ROUTING.value << BYTE0); + return (appID.appID() << BYTE1) | (ALLOC_ROUTING.value << BYTE0); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java index 7f5dc5827c..a0744ef00c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java @@ -67,7 +67,7 @@ private static int argument1(int numEntries, AppID appID) { throw new IllegalArgumentException( "numEntries must be no more than " + MAX_ENTRIES); } - return (numEntries << HALF1) | (appID.appID << BYTE1) | (2 << BYTE0); + return (numEntries << HALF1) | (appID.appID() << BYTE1) | (2 << BYTE0); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java index 23102bdef8..af718b14fe 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java @@ -75,7 +75,7 @@ public SDRAMAlloc(HasChipLocation chip, AppID appID, int size, int tag) { } private static int argument1(AppID appID) { - return (FLAG_TAG_RETRY << BYTE2) | (appID.appID << BYTE1) + return (FLAG_TAG_RETRY << BYTE2) | (appID.appID() << BYTE1) | (ALLOC_SDRAM.value << BYTE0); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java index ef7a135075..5b8e21d808 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java @@ -62,7 +62,7 @@ public SDRAMDeAlloc(HasChipLocation chip, MemoryLocation baseAddress) { } private static int argument1(AppID appID) { - return (appID.appID << BYTE1) | (FREE_SDRAM_BY_APP_ID.value << BYTE0); + return (appID.appID() << BYTE1) | (FREE_SDRAM_BY_APP_ID.value << BYTE0); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java index 4f487716c5..912b924f42 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java @@ -43,7 +43,7 @@ public SendSignal(AppID appID, Signal signal) { private static int argument2(AppID appID, Signal signal) { return (signal.value << BYTE2) | (APP_MASK << BYTE1) - | (appID.appID << BYTE0); + | (appID.appID() << BYTE0); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocClient.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocClient.java index 398bbe819d..f98cb5769d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocClient.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocClient.java @@ -220,7 +220,7 @@ public Version version(Integer timeout) if (log.isDebugEnabled()) { log.debug("version result: {}", result); } - return new Version(result); + return Version.parse(result); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java index 0f7caa8190..217d9f8366 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java @@ -679,8 +679,8 @@ public List getConnections() public String getHostname() throws IOException, SpallocServerException, InterruptedException { for (Connection c : getConnections()) { - if (c.getChip().onSameChipAs(ZERO_ZERO)) { - return c.getHostname(); + if (c.chip().onSameChipAs(ZERO_ZERO)) { + return c.hostname(); } } return null; @@ -902,7 +902,7 @@ public BoardPhysicalCoordinates whereIs(HasChipLocation chip) throw new IllegalStateException( "received null instead of machine location"); } - return result.getPhysical(); + return result.physical(); } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java index fdb4ab4831..f9201d3f51 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java @@ -33,42 +33,22 @@ /** * The logical coordinates of a board. This would be {@link TriadCoords} except * it has a different serialization form for backward-compatibility. + * + * @param x + * the X coordinate + * @param y + * the Y coordinate + * @param z + * the Z coordinate */ -@JsonPropertyOrder({ - "x", "y", "z" -}) +@JsonPropertyOrder({ "x", "y", "z" }) @JsonFormat(shape = ARRAY) @JsonAutoDetect(setterVisibility = NON_PRIVATE) @Immutable -public final class BoardCoordinates { - @ValidTriadX - private final int x; - - @ValidTriadY - private final int y; - - @ValidTriadZ - private final int z; - - /** - * Create with given coordinates. - * - * @param x - * the X coordinate - * @param y - * the Y coordinate - * @param z - * the Z coordinate - */ - public BoardCoordinates( - @JsonProperty(value = "x", defaultValue = "0") int x, - @JsonProperty(value = "y", defaultValue = "0") int y, - @JsonProperty(value = "z", defaultValue = "0") int z) { - this.x = x; - this.y = y; - this.z = z; - } - +public final record BoardCoordinates( + @JsonProperty(value = "x", defaultValue = "0") @ValidTriadX int x, + @JsonProperty(value = "y", defaultValue = "0") @ValidTriadY int y, + @JsonProperty(value = "z", defaultValue = "0") @ValidTriadZ int z) { /** * Create with given coordinates. * @@ -76,35 +56,7 @@ public BoardCoordinates( * the coordinates in standard form */ public BoardCoordinates(TriadCoords triad) { - this.x = triad.x; - this.y = triad.y; - this.z = triad.z; - } - - /** @return the X coordinate */ - public int getX() { - return x; - } - - /** @return the Y coordinate */ - public int getY() { - return y; - } - - /** @return the Z coordinate */ - public int getZ() { - return z; - } - - @Override - public boolean equals(Object o) { - return (o instanceof BoardCoordinates other) && (x == other.x) - && (y == other.y) && (z == other.z); - } - - @Override - public int hashCode() { - return x * 1234567 + y * 56789 + z; + this(triad.x(), triad.y(), triad.z()); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java index 79ae79fcb2..7d76ce6e7c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java @@ -31,69 +31,20 @@ * A combination of x, y, z and a Link. * * @author Christian + * @param x + * The X coordinate + * @param y + * The Y coordinate + * @param z + * The Z coordinate + * @param link + * The link number */ -@JsonPropertyOrder({ - "x", "y", "z", "link" -}) +@JsonPropertyOrder({ "x", "y", "z", "link" }) @JsonFormat(shape = ARRAY) @Immutable -public class BoardLink { +public record BoardLink(@JsonProperty("x") @ValidTriadX int x, + @JsonProperty("y") @ValidTriadY int y, + @JsonProperty("z") @ValidTriadZ int z, @JsonProperty("link") int link) { // TODO verify format and meaning. - - @ValidTriadX - private final int x; - - @ValidTriadY - private final int y; - - @ValidTriadZ - private final int z; - - private final int link; - - /** - * @param x - * The X coordinate - * @param y - * The Y coordinate - * @param z - * The Z coordinate - * @param link - * The link number - */ - public BoardLink(@JsonProperty("x") int x, @JsonProperty("y") int y, - @JsonProperty("z") int z, @JsonProperty("link") int link) { - this.x = x; - this.y = y; - this.z = z; - this.link = link; - } - - /** - * @return the X coordinate - */ - public int getX() { - return x; - } - - /** - * @return the Y coordinate - */ - public int getY() { - return y; - } - - /** - * @return the Z coordinate - */ - public int getZ() { - return z; - } - - /** - * @return the link number - */ - public int getLink() { - return link; - } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java index d926d9d5c3..810bd61264 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardPhysicalCoordinates.java @@ -18,9 +18,6 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE; import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; -import static java.util.Objects.isNull; - -import java.util.Objects; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; @@ -36,42 +33,25 @@ /** * The physical coordinates of a board. This would be {@link PhysicalCoords} * except it has a different serialization form for backward-compatibility. + * + * @param cabinet + * the cabinet ID + * @param frame + * the frame ID within the cabinet + * @param board + * the board ID within the frame */ -@JsonPropertyOrder({ - "cabinet", "frame", "board" -}) +@JsonPropertyOrder({ "cabinet", "frame", "board" }) @JsonFormat(shape = ARRAY) @JsonAutoDetect(setterVisibility = NON_PRIVATE) @Immutable -public class BoardPhysicalCoordinates { - @ValidCabinetNumber - private final int cabinet; - - @ValidFrameNumber - private final int frame; - - @ValidBoardNumber - private final Integer board; - - /** - * Create with given coordinates. - * - * @param cabinet - * the cabinet ID - * @param frame - * the frame ID within the cabinet - * @param board - * the board ID within the frame - */ - public BoardPhysicalCoordinates( - @JsonProperty(value = "cabinet", defaultValue = "0") int cabinet, - @JsonProperty(value = "frame", defaultValue = "0") int frame, - @JsonProperty(value = "board", defaultValue = "0") Integer board) { - this.cabinet = cabinet; - this.frame = frame; - this.board = board; - } - +public record BoardPhysicalCoordinates( + @JsonProperty(value = "cabinet", defaultValue = "0") // + @ValidCabinetNumber int cabinet, + @JsonProperty(value = "frame", defaultValue = "0") // + @ValidFrameNumber int frame, + @JsonProperty(value = "board", defaultValue = "0") // + @ValidBoardNumber Integer board) { /** * Create with given coordinates. * @@ -79,37 +59,7 @@ public BoardPhysicalCoordinates( * the coordinates in standard form. */ public BoardPhysicalCoordinates(PhysicalCoords coords) { - this.cabinet = coords.c; - this.frame = coords.f; - this.board = coords.b; - } - - /** @return the cabinet ID */ - public int getCabinet() { - return cabinet; - } - - /** @return the frame ID within the cabinet */ - public int getFrame() { - return frame; - } - - /** @return the board ID within the frame */ - public Integer getBoard() { - return board; - } - - @Override - public boolean equals(Object o) { - return (o instanceof BoardPhysicalCoordinates other) - && (cabinet == other.cabinet) && (frame == other.frame) - && Objects.equals(board, other.board); - } - - @Override - public int hashCode() { - return 9 * (cabinet * 1234567 + frame * 56789 - + (isNull(board) ? 0 : board)); + this(coords.c(), coords.f(), coords.b()); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java index 21127c0682..c5ad3cefd3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java @@ -19,8 +19,6 @@ import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; import static java.util.Objects.isNull; -import java.util.Objects; - import javax.validation.Valid; import com.fasterxml.jackson.annotation.JsonFormat; @@ -36,20 +34,18 @@ /** * Describes a connection by its chip and hostname. + * + * @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) @JsonDeserialize(builder = Connection.Builder.class) @Immutable -public final class Connection { - @Valid - private final ChipLocation chip; - - @IPAddress - private final String hostname; - +public final record Connection(@Valid ChipLocation chip, + @IPAddress String hostname) { /** * Create. * @@ -59,29 +55,7 @@ public final class Connection { * the host */ public Connection(HasChipLocation chip, String hostname) { - this.chip = isNull(chip) ? null : 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) { - return (other instanceof Connection c) && Objects.equals(chip, c.chip) - && Objects.equals(hostname, c.hostname); - } - - @Override - public int hashCode() { - return Objects.hash(hostname, chip); + this(isNull(chip) ? null : chip.asChipLocation(), hostname); } @Override @@ -89,9 +63,7 @@ public String toString() { return "Connection(" + chip + "@" + hostname + ")"; } - @JsonPropertyOrder({ - "chip", "hostname" - }) + @JsonPropertyOrder({ "chip", "hostname" }) @JsonFormat(shape = ARRAY) @JsonPOJOBuilder static class Builder { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java index dc34524bda..550082b9ee 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java @@ -43,8 +43,8 @@ public GetBoardAtPositionCommand(@NotBlank String machine, super("get_board_at_position"); addKwArg("machine_name", machine); // The current spalloc server expects the param names x, y, z - addKwArg("x", coords.c); - addKwArg("y", coords.f); - addKwArg("z", coords.b); + addKwArg("x", coords.c()); + addKwArg("y", coords.f()); + addKwArg("z", coords.b()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java index 36ca75f6c7..9147949a74 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java @@ -43,8 +43,8 @@ public GetBoardPositionCommand(@NotBlank String machine, @Valid TriadCoords coords) { super("get_board_position"); addKwArg("machine_name", machine); - addKwArg("x", coords.x); - addKwArg("y", coords.y); - addKwArg("z", coords.z); + addKwArg("x", coords.x()); + addKwArg("y", coords.y()); + addKwArg("z", coords.z()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java index db6837d7e2..2c1b6099b6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java @@ -16,8 +16,6 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import java.util.Objects; - import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.google.errorprone.annotations.Immutable; @@ -26,134 +24,27 @@ /** * The description of where some resource is on a SpiNNaker system. + * + * @param jobChip + * the chip location relative to the job's allocation. + * @param jobId + * the job id. + * @param chip + * the absolute chip location. + * @param logical + * the logical coordinates of the board + * @param machine + * the name of the machine + * @param boardChip + * the chip location relative to its board + * @param physical + * the physical coordinates of the board */ @Immutable @JsonDeserialize(builder = WhereIs.Builder.class) -public final class WhereIs { - private final ChipLocation jobChip; - - private final Integer jobId; - - private final ChipLocation chip; - - private final BoardCoordinates logical; - - private final String machine; - - private final ChipLocation boardChip; - - private final BoardPhysicalCoordinates physical; - - /** - * Create. - * - * @param jobChip - * the chip location relative to the job's allocation. - * @param jobId - * the job id. - * @param chip - * the absolute chip location. - * @param logical - * the logical coordinates of the board - * @param machine - * the name of the machine - * @param boardChip - * the chip location relative to its board - * @param physical - * the physical coordinates of the board - */ - public WhereIs(ChipLocation jobChip, Integer jobId, ChipLocation chip, - BoardCoordinates logical, String machine, ChipLocation boardChip, - BoardPhysicalCoordinates physical) { - this.jobChip = jobChip; - this.jobId = jobId; - this.chip = chip; - this.logical = logical; - this.machine = machine; - this.boardChip = boardChip; - this.physical = physical; - } - - /** - * Get the chip location relative to the job's allocation. - * - * @return the job-relative chip location - */ - public ChipLocation getJobChip() { - return jobChip; - } - - /** - * Get the job id. - * - * @return the job id - */ - public Integer getJobId() { - return jobId; - } - - /** - * Get the chip. - * - * @return the chip - */ - public ChipLocation getChip() { - return chip; - } - - /** - * Get the logical board coordinates. - * - * @return the logical board coordinates - */ - public BoardCoordinates getLogical() { - return logical; - } - - /** - * Get the machine. - * - * @return the machine - */ - public String getMachine() { - return machine; - } - - /** - * Get the chip location relative to the board. - * - * @return the board chip location - */ - public ChipLocation getBoardChip() { - return boardChip; - } - - /** - * Get the physical board coordinates. - * - * @return the physical board coordinates - */ - public BoardPhysicalCoordinates getPhysical() { - return physical; - } - - @Override - public boolean equals(Object o) { - return (o instanceof WhereIs other) - && Objects.equals(jobChip, other.jobChip) - && Objects.equals(jobId, other.jobId) - && Objects.equals(chip, other.chip) - && Objects.equals(logical, other.logical) - && Objects.equals(machine, other.machine) - && Objects.equals(boardChip, other.boardChip) - && Objects.equals(physical, other.physical); - } - - @Override - public int hashCode() { - throw new UnsupportedOperationException(); - } - +public final record WhereIs(ChipLocation jobChip, Integer jobId, + ChipLocation chip, BoardCoordinates logical, String machine, + ChipLocation boardChip, BoardPhysicalCoordinates physical) { @Override public String toString() { return "jobChip: " + jobChip + " jobId: " + jobId + " chip: " + chip diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java index e3986abae0..584339c78b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java @@ -42,8 +42,8 @@ public WhereIsMachineBoardLogicalCommand(@NotBlank String machine, @Valid TriadCoords coords) { super("where_is"); addKwArg("machine", machine); - addKwArg("x", coords.x); - addKwArg("y", coords.y); - addKwArg("z", coords.z); + addKwArg("x", coords.x()); + addKwArg("y", coords.y()); + addKwArg("z", coords.z()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java index 069b68b15f..55a19736af 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java @@ -43,8 +43,8 @@ public WhereIsMachineBoardPhysicalCommand(@NotBlank String machine, @Valid @NotNull PhysicalCoords coords) { super("where_is"); addKwArg("machine", machine); - addKwArg("cabinet", coords.c); - addKwArg("frame", coords.f); - addKwArg("board", coords.b); + addKwArg("cabinet", coords.c()); + addKwArg("frame", coords.f()); + addKwArg("board", coords.b()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/AppIdTracker.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/AppIdTracker.java index 649cf7809d..077ab6b043 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/AppIdTracker.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/AppIdTracker.java @@ -126,7 +126,7 @@ public void allocateID(AppID id) { * if the ID is out of range */ public void freeID(AppID id) { - if (id.appID < minID || id.appID > maxID) { + if (id.appID() < minID || id.appID() > maxID) { throw new IllegalArgumentException( "ID " + id + " out of allowed range of " + minID + " to " + maxID); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java index 5e7ab84ab9..b48c947bcd 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java @@ -221,39 +221,29 @@ private IntBuffer readFromAddress(HasChipLocation chip, } @SARKStruct("heap_t") - private static class HeapHeader { - @SARKField("free") - final MemoryLocation free; - - @SARKField("first") - final MemoryLocation first; - - @SARKField("last") - final MemoryLocation last; - - @SARKField("free_bytes") - final int freeBytes; - + private static record HeapHeader(// + @SARKField("free") MemoryLocation free, + @SARKField("first") MemoryLocation first, + @SARKField("last") MemoryLocation last, + @SARKField("free_bytes") int freeBytes) { HeapHeader(IntBuffer data) { - free = new MemoryLocation(data.get()); - first = new MemoryLocation(data.get()); - last = new MemoryLocation(data.get()); - freeBytes = data.get(); + this(// + new MemoryLocation(data.get()), + new MemoryLocation(data.get()), + new MemoryLocation(data.get()), // + data.get()); // Note that we don't read or look at the 'buffer' field } } @SARKStruct("block_t") - private static class BlockHeader { - @SARKField("next") - final MemoryLocation next; - - @SARKField("free") - final MemoryLocation free; - + private static record BlockHeader(// + @SARKField("next") MemoryLocation next, + @SARKField("free") MemoryLocation free) { BlockHeader(IntBuffer data) { - next = new MemoryLocation(data.get()); - free = new MemoryLocation(data.get()); + this(// + new MemoryLocation(data.get()), + new MemoryLocation(data.get())); } } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 01ff05fd65..be7f1560b6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -748,8 +748,8 @@ private Object getSystemVariable(HasChipLocation chip, private ConnectionSelector bmpConnection(BMPCoords bmp) { if (!bmpSelectors.containsKey(bmp)) { throw new IllegalArgumentException( - "Unknown combination of cabinet (" + bmp.getCabinet() - + ") and frame (" + bmp.getFrame() + ")"); + "Unknown combination of cabinet (" + bmp.cabinet() + + ") and frame (" + bmp.frame() + ")"); } return bmpSelectors.get(bmp); } @@ -801,7 +801,7 @@ private void checkBMPConnections() try { var versionInfo = readBMPVersion(conn.getCoords(), conn.boards); if (!BMP_NAME.equals(versionInfo.name) || !BMP_MAJOR_VERSIONS - .contains(versionInfo.versionNumber.majorVersion)) { + .contains(versionInfo.versionNumber.majorVersion())) { throw new IOException(format( "The BMP at %s is running %s %s which is " + "incompatible with this transceiver, " @@ -1114,24 +1114,7 @@ public void bootBoard(Map extraBootValues) * @return true exactly when they are compatible */ public static boolean isScampVersionCompatible(Version version) { - // The major version must match exactly - if (version.majorVersion != SCAMP_VERSION.majorVersion) { - return false; - } - - /* - * If the minor version matches, the patch version must be >= the - * required version - */ - if (version.minorVersion == SCAMP_VERSION.minorVersion) { - return version.revision >= SCAMP_VERSION.revision; - } - - /* - * If the minor version is > than the required version, the patch - * version is irrelevant - */ - return version.minorVersion > SCAMP_VERSION.minorVersion; + return version.compatibleWith(SCAMP_VERSION); } /** @@ -2598,17 +2581,16 @@ ConnectionSelector> getBMPConnection() { /** * A simple description of a connnection to create. + * + * @param hostname + * What host to talk to. + * @param portNumber + * What port to talk to, or {@code null} for default. + * @param chip + * What chip to talk to. */ - public static final class ConnectionDescriptor { - /** What host to talk to. */ - private InetAddress hostname; - - /** What port to talk to, or {@code null} for default. */ - private Integer portNumber; - - /** What chip to talk to. */ - private ChipLocation chip; - + public static final record ConnectionDescriptor(InetAddress hostname, + Integer portNumber, ChipLocation chip) { /** * Create a connection descriptor. * @@ -2619,9 +2601,7 @@ public static final class ConnectionDescriptor { */ public ConnectionDescriptor(InetAddress hostname, HasChipLocation chip) { - this.hostname = requireNonNull(hostname); - this.chip = chip.asChipLocation(); - this.portNumber = null; + this(requireNonNull(hostname), null, chip.asChipLocation()); } /** @@ -2636,9 +2616,7 @@ public ConnectionDescriptor(InetAddress hostname, */ public ConnectionDescriptor(InetAddress host, int port, HasChipLocation chip) { - this.hostname = requireNonNull(host); - this.chip = chip.asChipLocation(); - this.portNumber = port; + this(requireNonNull(host), (Integer) port, chip.asChipLocation()); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java index 0438a88f69..a1a102f05f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java @@ -2504,10 +2504,10 @@ ByteBuffer readMemory(@Valid HasCoreLocation core, default ByteBuffer readMemory(@Valid HasCoreLocation core, @NotNull HeapElement element) throws IOException, ProcessException, InterruptedException { - if (element.isFree) { + if (element.isFree()) { return null; } - return readMemory(core, element.getDataAddress(), element.size); + return readMemory(core, element.dataAddress(), element.size()); } /** @@ -3971,8 +3971,8 @@ void setReinjectionEmergencyTimeout(@Valid HasCoreLocation monitorCore, default void setReinjectionEmergencyTimeout( @Valid HasCoreLocation monitorCore, @NotNull RouterTimeout timeout) throws IOException, ProcessException, InterruptedException { - setReinjectionEmergencyTimeout(monitorCore, timeout.mantissa, - timeout.exponent); + setReinjectionEmergencyTimeout(monitorCore, timeout.mantissa(), + timeout.exponent()); } /** @@ -4014,8 +4014,8 @@ void setReinjectionEmergencyTimeout(@Valid CoreSubsets monitorCores, default void setReinjectionEmergencyTimeout(@Valid CoreSubsets monitorCores, @NotNull RouterTimeout timeout) throws IOException, ProcessException, InterruptedException { - setReinjectionEmergencyTimeout(monitorCores, timeout.mantissa, - timeout.exponent); + setReinjectionEmergencyTimeout(monitorCores, timeout.mantissa(), + timeout.exponent()); } /** @@ -4037,7 +4037,7 @@ default void setReinjectionEmergencyTimeout(@Valid CoreSubsets monitorCores, @NotNull ReinjectionStatus status) throws IOException, ProcessException, InterruptedException { setReinjectionEmergencyTimeout(monitorCores, - status.getEmergencyTimeout()); + status.emergencyTimeout()); } /** @@ -4079,7 +4079,8 @@ void setReinjectionTimeout(@Valid HasCoreLocation monitorCore, default void setReinjectionTimeout(@Valid HasCoreLocation monitorCore, @NotNull RouterTimeout timeout) throws IOException, ProcessException, InterruptedException { - setReinjectionTimeout(monitorCore, timeout.mantissa, timeout.exponent); + setReinjectionTimeout(monitorCore, timeout.mantissa(), + timeout.exponent()); } /** @@ -4121,7 +4122,8 @@ void setReinjectionTimeout(@Valid CoreSubsets monitorCores, default void setReinjectionTimeout(@Valid CoreSubsets monitorCores, @NotNull RouterTimeout timeout) throws IOException, ProcessException, InterruptedException { - setReinjectionTimeout(monitorCores, timeout.mantissa, timeout.exponent); + setReinjectionTimeout(monitorCores, timeout.mantissa(), + timeout.exponent()); } /** @@ -4142,7 +4144,7 @@ default void setReinjectionTimeout(@Valid CoreSubsets monitorCores, default void setReinjectionTimeout(@Valid CoreSubsets monitorCores, @NotNull ReinjectionStatus status) throws IOException, ProcessException, InterruptedException { - setReinjectionTimeout(monitorCores, status.getTimeout()); + setReinjectionTimeout(monitorCores, status.timeout()); } /** diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java index 2c4fed98e9..13f93a7513 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java @@ -27,33 +27,33 @@ public class TestVersion { @Test public void testThreeUnquoted() { - var version = new Version("1.2.3"); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(3, version.revision); + var version = Version.parse("1.2.3"); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(3, version.revision()); } @Test public void testThreeQuoted() { - var version = new Version("\"1.2.3\""); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(3, version.revision); + var version = Version.parse("\"1.2.3\""); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(3, version.revision()); } @Test public void testTwoUnquoted() { - var version = new Version("1.2"); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(0, version.revision); + var version = Version.parse("1.2"); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(0, version.revision()); } @Test public void testOneQuoted() { - var version = new Version("\"1\""); - assertEquals(1, version.majorVersion); - assertEquals(0, version.minorVersion); - assertEquals(0, version.revision); + var version = Version.parse("\"1\""); + assertEquals(1, version.majorVersion()); + assertEquals(0, version.minorVersion()); + assertEquals(0, version.revision()); } } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/SupportUtils.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/SupportUtils.java index dbcc9df139..2668a3e480 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/SupportUtils.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/SupportUtils.java @@ -62,6 +62,13 @@ interface Joinable { interface IServer extends AutoCloseable { void send(JSONObject obj); + /** + * Arrange for a message to be sent. + * + * @param jsonString + * The JSON message to be sent. Will be parsed and + * reformatted for the protocol. + */ default void send(String jsonString) { send(new JSONObject(jsonString)); } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java index 12fc9b7a6d..4f018fa0b0 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java @@ -56,8 +56,21 @@ static class MockCommand extends Command { } } - private static final String MOCK_RECEIVED_MESSAGE = - "{\"command\": \"foo\", \"args\": [1], \"kwargs\": {\"bar\": 2}}"; + private static final String MOCK_RECEIVED_MESSAGE = """ + { + "command": "foo", + "args": [1], + "kwargs": { + "bar": 2 + } + } + """; + + private static final String VOID_RETURN = """ + { + "return": null + } + """; @Test void testConnectNoServer() throws Exception { @@ -121,7 +134,11 @@ void testReceiveJson() throws Exception { assertTimeout(before, after); // Transfer an actual message - s.send("{\"return\": \"bar\"}"); + s.send(""" + { + "return": "bar" + } + """); assertEquals("\"bar\"", ((ReturnResponse) c.receiveResponse(null)) .getReturnValue()); @@ -140,22 +157,42 @@ void testReceiveJson() throws Exception { } // Test message ordering - s.send("{\"return\": \"foo\"}"); - s.send("{\"return\": \"bar\"}"); + s.send(""" + { + "return": "foo" + } + """); + s.send(""" + { + "return": "bar" + } + """); assertEquals("\"foo\"", ((ReturnResponse) c.receiveResponse(null)) .getReturnValue()); assertEquals("\"bar\"", ((ReturnResponse) c.receiveResponse(null)) .getReturnValue()); // Test other message types - s.send("{\"exception\": \"bar\"}"); + s.send(""" + { + "exception": "bar" + } + """); assertEquals("bar", ((ExceptionResponse) c.receiveResponse(null)) .getException()); - s.send("{\"machines_changed\": [\"foo\",\"bar\"]}"); + s.send(""" + { + "machines_changed": ["foo", "bar"] + } + """); assertEquals(List.of("foo", "bar"), ((MachinesChangedNotification) c.receiveResponse(null)) .getMachinesChanged()); - s.send("{\"jobs_changed\": [1, 2]}"); + s.send(""" + { + "jobs_changed": [1, 2] + } + """); assertEquals(List.of(1, 2), ((JobsChangedNotification) c.receiveResponse(null)) .getJobsChanged()); @@ -178,9 +215,13 @@ void testSendJson() throws Exception { // Make sure we can send JSON c.sendCommand(new VersionCommand(), 250); - JSONAssert.assertEquals( - "{\"command\":\"version\",\"args\":[],\"kwargs\":{}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command":"version", + "args":[], + "kwargs":{} + } + """, s.recv(), true); }); } @@ -191,7 +232,11 @@ void testCall() throws Exception { bgAccept.join(); // Basic calls should work - s.send("{\"return\": \"Woo\"}"); + s.send(""" + { + "return": "Woo" + } + """); assertEquals("\"Woo\"", c.call(new MockCommand("foo", 1, "bar", 2), null)); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); @@ -200,9 +245,21 @@ void testCall() throws Exception { * Should be able to cope with notifications arriving before return * value */ - s.send("{\"jobs_changed\": [1]}"); - s.send("{\"jobs_changed\": [2]}"); - s.send("{\"return\": \"Woo\"}"); + s.send(""" + { + "jobs_changed": [1] + } + """); + s.send(""" + { + "jobs_changed": [2] + } + """); + s.send(""" + { + "return": "Woo" + } + """); assertEquals("\"Woo\"", c.call(new MockCommand("foo", 1, "bar", 2), null)); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); @@ -222,7 +279,11 @@ void testCall() throws Exception { assertTimeout(before, after); // Should be able to timeout after getting a notification - s.send("{\"jobs_changed\": [3]}"); + s.send(""" + { + "jobs_changed": [3] + } + """); before = System.currentTimeMillis(); assertThrows(SpallocProtocolTimeoutException.class, () -> c.call(new MockCommand("foo", 1, "bar", 2), TIMEOUT)); @@ -258,8 +319,16 @@ void testWaitForNotification() throws Exception { // If notifications queued during call, should just return // those - s.send("{\"jobs_changed\": [1]}"); - s.send("{\"jobs_changed\": [2]}"); + s.send(""" + { + "jobs_changed": [1] + } + """); + s.send(""" + { + "jobs_changed": [2] + } + """); s.send("{\"return\": \"Woo\"}"); assertEquals("\"Woo\"", c.call(new MockCommand("foo", 1, "bar", 2), null)); @@ -270,7 +339,11 @@ void testWaitForNotification() throws Exception { c.waitForNotification()); // If no notifications queued, should listen for them - s.send("{\"jobs_changed\": [3]}"); + s.send(""" + { + "jobs_changed": [3] + } + """); assertEquals(new JobsChangedNotification(3), c.waitForNotification()); }); @@ -284,21 +357,40 @@ void testCommandCreateJob() throws Exception { bgAccept.join(); // Old style create_job - s.send("{\"return\": 123}"); + s.send(""" + { + "return": 123 + } + """); Map kwargs = Map.of("bar", 2, "owner", "dummy"); assertEquals(123, c.createJob(List.of(1), kwargs)); - JSONAssert.assertEquals( - "{\"command\": \"create_job\", \"args\": [1], " - + "\"kwargs\": {\"owner\": \"dummy\"}}", + JSONAssert.assertEquals(""" + { + "command": "create_job", + "args": [1], + "kwargs": { + "owner": "dummy" + } + } + """, s.recv(), true); // New style create_job - s.send("{\"return\": 123}"); + s.send(""" + { + "return": 123 + } + """); assertEquals(123, c.createJob(new CreateJob(1).owner("dummy"))); - JSONAssert.assertEquals( - "{\"command\": \"create_job\", \"args\": [1], " - + "\"kwargs\": {\"owner\": \"dummy\"}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "create_job", + "args": [1], + "kwargs": { + "owner": "dummy" + } + } + """, s.recv(), true); }); } @@ -308,13 +400,25 @@ void testCommandListJobs() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":[{\"job_id\":123},{\"job_id\":99}]}"); + s.send(""" + { + "return": [ + {"job_id": 123}, + {"job_id": 99} + ] + } + """); var result = c.listJobs(); assertEquals(2, result.size()); assertEquals(123, result.get(0).getJobID()); assertEquals(99, result.get(1).getJobID()); - JSONAssert.assertEquals("{\"command\": \"list_jobs\", " - + "\"args\": [], \"kwargs\": {}}", s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "list_jobs", + "args": [], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -324,13 +428,24 @@ void testCommandListMachines() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":[{\"name\":\"foo\"},{\"name\":\"bar\"}]}"); + s.send(""" + { + "return": [ + {"name": "foo"}, {"name": "bar"} + ] + } + """); var result = c.listMachines(); assertEquals(2, result.size()); assertEquals("foo", result.get(0).getName()); assertEquals("bar", result.get(1).getName()); - JSONAssert.assertEquals("{\"command\": \"list_machines\", " - + "\"args\": [], \"kwargs\": {}}", s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "list_machines", + "args": [], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -340,12 +455,17 @@ void testCommandDestroyJob() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":null}"); + s.send(VOID_RETURN); c.destroyJob(123, "gorp"); - JSONAssert.assertEquals( - "{\"command\": \"destroy_job\", " + "\"args\": [123], " - + "\"kwargs\": {\"reason\":\"gorp\"}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "destroy_job", + "args": [123], + "kwargs": { + "reason": "gorp" + } + } + """, s.recv(), true); }); } @@ -355,20 +475,45 @@ void testCommandGetBoardPosition() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":[4,5,6]}"); + s.send(""" + { + "return": [4, 5, 6] + } + """); var pc = c.getBoardPosition("gorp", new BoardCoordinates(1, 2, 3)); assertEquals(new BoardPhysicalCoordinates(4, 5, 6), pc); - JSONAssert.assertEquals("{\"command\": \"get_board_position\", " - + "\"args\": [], \"kwargs\": " - + "{\"machine_name\":\"gorp\",\"x\":1,\"y\":2,\"z\":3}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "get_board_position", + "args": [], + "kwargs": { + "machine_name": "gorp", + "x": 1, + "y": 2, + "z": 3 + } + } + """, s.recv(), true); - s.send("{\"return\":[7,8,9]}"); + s.send(""" + { + "return": [7, 8, 9] + } + """); var lc = c.getBoardPosition("gorp", pc); assertEquals(new BoardCoordinates(7, 8, 9), lc); - JSONAssert.assertEquals("{\"command\": \"get_board_at_position\", " - + "\"args\": [], \"kwargs\": " - + "{\"machine_name\":\"gorp\",\"x\":4,\"y\":5,\"z\":6}}", + JSONAssert.assertEquals(""" + { + "command": "get_board_at_position", + "args": [], + "kwargs": { + "machine_name": "gorp", + "x": 4, + "y": 5, + "z": 6 + } + } + """, s.recv(), true); }); } @@ -379,20 +524,33 @@ void testCommandGetJobMachineInfo() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":{\"boards\": [[1,2,3]]," - + "\"connections\": [[[1,2],\"gorp\"]]}}"); + s.send(""" + { + "return": { + "boards": [ + [1, 2, 3] + ], + "connections": [ + [[1, 2], "gorp"] + ] + } + } + """); var result = c.getJobMachineInfo(123); var boards = result.getBoards(); assertEquals(1, boards.size()); assertEquals(new BoardCoordinates(1, 2, 3), boards.get(0)); var conns = result.getConnections(); assertEquals(1, conns.size()); - assertEquals(new ChipLocation(1, 2), conns.get(0).getChip()); - assertEquals("gorp", conns.get(0).getHostname()); - JSONAssert.assertEquals( - "{\"command\": \"get_job_machine_info\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); + assertEquals(new ChipLocation(1, 2), conns.get(0).chip()); + assertEquals("gorp", conns.get(0).hostname()); + JSONAssert.assertEquals(""" + { + "command": "get_job_machine_info", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -402,14 +560,24 @@ void testCommandGetJobState() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":{\"state\":3,\"power\":true}}"); + s.send(""" + { + "return": { + "state": 3, + "power": true + } + } + """); var result = c.getJobState(123); assertEquals(true, result.getPower()); assertEquals(READY, result.getState()); - JSONAssert.assertEquals( - "{\"command\": \"get_job_state\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "get_job_state", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -419,18 +587,24 @@ void testCommandNotifyJob() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":null}"); + s.send(VOID_RETURN); c.notifyJob(123, false); - JSONAssert.assertEquals( - "{\"command\": \"no_notify_job\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); - s.send("{\"return\":null}"); + JSONAssert.assertEquals(""" + { + "command": "no_notify_job", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); + s.send(VOID_RETURN); c.notifyJob(123, true); - JSONAssert.assertEquals( - "{\"command\": \"notify_job\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "notify_job", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -440,18 +614,24 @@ void testCommandNotifyMachine() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":null}"); + s.send(VOID_RETURN); c.notifyMachine("foo", false); - JSONAssert.assertEquals( - "{\"command\": \"no_notify_machine\", " - + "\"args\": [\"foo\"], \"kwargs\": {}}", - s.recv(), true); - s.send("{\"return\":null}"); + JSONAssert.assertEquals(""" + { + "command": "no_notify_machine", + "args": ["foo"], + "kwargs": {} + } + """, s.recv(), true); + s.send(VOID_RETURN); c.notifyMachine("foo", true); - JSONAssert.assertEquals( - "{\"command\": \"notify_machine\", " - + "\"args\": [\"foo\"], \"kwargs\": {}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "notify_machine", + "args": ["foo"], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -461,18 +641,24 @@ void testCommandPower() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":null}"); + s.send(VOID_RETURN); c.powerOffJobBoards(123); - JSONAssert.assertEquals( - "{\"command\": \"power_off_job_boards\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); - s.send("{\"return\":null}"); + JSONAssert.assertEquals(""" + { + "command": "power_off_job_boards", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); + s.send(VOID_RETURN); c.powerOnJobBoards(123); - JSONAssert.assertEquals( - "{\"command\": \"power_on_job_boards\", " - + "\"args\": [123], \"kwargs\": {}}", - s.recv(), true); + JSONAssert.assertEquals(""" + { + "command": "power_on_job_boards", + "args": [123], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -482,14 +668,22 @@ void testCommandVersion() throws Exception { c.connect(); bgAccept.join(); - s.send("{\"return\":\"1.2.3\"}"); + s.send(""" + { + "return": "1.2.3" + } + """); var result = c.version(); - assertEquals(1, result.majorVersion); - assertEquals(2, result.minorVersion); - assertEquals(3, result.revision); - JSONAssert.assertEquals( - "{\"command\": \"version\", \"args\": [], \"kwargs\": {}}", - s.recv(), true); + assertEquals(1, result.majorVersion()); + assertEquals(2, result.minorVersion()); + assertEquals(3, result.revision()); + JSONAssert.assertEquals(""" + { + "command": "version", + "args": [], + "kwargs": {} + } + """, s.recv(), true); }); } @@ -500,42 +694,94 @@ void testCommandWhereIs() throws Exception { bgAccept.join(); WhereIs result; - s.send("{\"return\":{\"machine\":\"gorp\",\"logical\":[2,3,4]}}"); + s.send(""" + { + "return": { + "machine": "gorp", + "logical": [2, 3, 4] + } + } + """); result = c.whereIs(123, new ChipLocation(1, 2)); - assertEquals("gorp", result.getMachine()); - assertEquals(new BoardCoordinates(2, 3, 4), result.getLogical()); - JSONAssert.assertEquals( - "{\"command\": \"where_is\", \"args\": [], \"kwargs\": {" - + "\"chip_x\":1,\"chip_y\":2,\"job_id\":123}}", - s.recv(), true); + assertEquals("gorp", result.machine()); + assertEquals(new BoardCoordinates(2, 3, 4), result.logical()); + JSONAssert.assertEquals(""" + { + "command": "where_is", + "args": [], + "kwargs": { + "chip_x": 1, + "chip_y": 2, + "job_id": 123 + } + } + """, s.recv(), true); - s.send("{\"return\":{\"physical\":[2,3,4]}}"); + s.send(""" + { + "return": { + "physical": [2, 3, 4] + } + } + """); result = c.whereIs("gorp", new BoardCoordinates(1, 2, 3)); assertEquals(new BoardPhysicalCoordinates(2, 3, 4), - result.getPhysical()); - JSONAssert.assertEquals( - "{\"command\": \"where_is\", \"args\": [], \"kwargs\": {" - + "\"x\":1,\"y\":2,\"z\":3,\"machine\":\"gorp\"" - + "}}", - s.recv(), true); + result.physical()); + JSONAssert.assertEquals(""" + { + "command": "where_is", + "args": [], + "kwargs": { + "x": 1, + "y": 2, + "z": 3, + "machine": "gorp" + } + } + """, s.recv(), true); - s.send("{\"return\":{\"logical\":[2,3,4]}}"); + s.send(""" + { + "return": { + "logical": [2, 3, 4] + } + } + """); result = c.whereIs("gorp", new BoardPhysicalCoordinates(1, 2, 3)); - assertEquals(new BoardCoordinates(2, 3, 4), result.getLogical()); - JSONAssert.assertEquals( - "{\"command\": \"where_is\", \"args\": [], \"kwargs\": {" - + "\"cabinet\":1,\"frame\":2,\"board\":3," - + "\"machine\":\"gorp\"}}", - s.recv(), true); + assertEquals(new BoardCoordinates(2, 3, 4), result.logical()); + JSONAssert.assertEquals(""" + { + "command": "where_is", + "args": [], + "kwargs": { + "cabinet": 1, + "frame": 2, + "board": 3, + "machine": "gorp" + } + } + """, s.recv(), true); - s.send("{\"return\":{\"logical\":[2,3,4]}}"); + s.send(""" + { + "return": { + "logical": [2, 3, 4] + } + } + """); result = c.whereIs("gorp", new ChipLocation(0, 1)); - assertEquals(new BoardCoordinates(2, 3, 4), result.getLogical()); - JSONAssert.assertEquals( - "{\"command\": \"where_is\", \"args\": [], \"kwargs\": {" - + "\"chip_x\":0,\"chip_y\":1," - + "\"machine\":\"gorp\"}}", - s.recv(), true); + assertEquals(new BoardCoordinates(2, 3, 4), result.logical()); + JSONAssert.assertEquals(""" + { + "command": "where_is", + "args": [], + "kwargs": { + "chip_x": 0, + "chip_y": 1, + "machine": "gorp" + } + } + """, s.recv(), true); }); } } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java index 8579bf067c..3f6a047dbf 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java @@ -110,34 +110,63 @@ void testCoreJobFlow() throws Exception { }); // Check that the messages sent were the ones we expected - JSONAssert.assertEquals("{\"command\": \"create_job\", " - + "\"args\": [1, 2, 3], \"kwargs\": {" - + "\"keepalive\": 1, \"max_dead_boards\": 0, " - + "\"min_ratio\": 0.333, \"owner\": \"dummy\", " - + "\"require_torus\": false}}", received.take(), true); - JSONAssert.assertEquals( - "{\"command\": \"power_on_job_boards\", \"args\": [123], " - + "\"kwargs\": {}}", - received.take(), true); - JSONAssert.assertEquals( - "{\"command\": \"get_job_state\", \"args\": [123], " - + "\"kwargs\": {}}", - received.take(), true); - JSONAssert - .assertEquals("{\"command\": \"notify_job\", \"args\": [123], " - + "\"kwargs\": {}}", received.take(), true); - JSONAssert.assertEquals( - "{\"command\": \"get_job_state\", \"args\": [123], " - + "\"kwargs\": {}}", - received.take(), true); - JSONAssert.assertEquals( - "{\"command\": \"get_job_machine_info\", \"args\": [123], " - + "\"kwargs\": {}}", - received.take(), true); - JSONAssert.assertEquals( - "{\"command\": \"destroy_job\", \"args\": [123], " - + "\"kwargs\": {\"reason\": \"abc\"}}", - received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "create_job", + "args": [1, 2, 3], + "kwargs": { + "keepalive": 1, + "max_dead_boards": 0, + "min_ratio": 0.333, + "owner": "dummy", + "require_torus": false + } + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "power_on_job_boards", + "args": [123], + "kwargs": {} + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "get_job_state", + "args": [123], + "kwargs": {} + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "notify_job", + "args": [123], + "kwargs": {} + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "get_job_state", + "args": [123], + "kwargs": {} + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "get_job_machine_info", + "args": [123], + "kwargs": {} + } + """, received.take(), true); + JSONAssert.assertEquals(""" + { + "command": "destroy_job", + "args": [123], + "kwargs": { + "reason": "abc" + } + } + """, received.take(), true); assertTrue(received.isEmpty(), "must have checked all received messages"); assertTrue(send.isEmpty(), "must have sent all expected responses"); @@ -150,10 +179,13 @@ void testCoreJobFlow() throws Exception { // All should have the same message sent var first = keepalives.take(); assertNotNull(first, "null in keepalive queue!"); - JSONAssert.assertEquals( - "{\"command\": \"job_keepalive\", " - + "\"args\": [123], \"kwargs\": {}}", - first, true); + JSONAssert.assertEquals(""" + { + "command": "job_keepalive", + "args": [123], + "kwargs": {} + } + """, first, true); while (!keepalives.isEmpty()) { JSONAssert.assertEquals(first, keepalives.take(), true); } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestMockClient.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestMockClient.java index 1627db4ad8..d2b01ad0b0 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestMockClient.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestMockClient.java @@ -118,7 +118,7 @@ void testListMachines() boolean previous = client.isActual(); var whereis1 = client.whereIs(machineName, coords, timeout); var whereis2 = client.whereIs(machineName, physical, timeout); - var chip = whereis1.getChip(); + var chip = whereis1.chip(); var whereis3 = client.whereIs(machineName, chip, timeout); // check only work if all real or all mock if (previous == client.isActual()) { @@ -170,7 +170,7 @@ void testJob() throws IOException, SpallocServerException, Exception { assertEquals("Spin24b-223", machineName); } var connections = machineInfo.getConnections(); - var hostName = connections.get(0).getHostname(); + var hostName = connections.get(0).hostname(); if (client.isActual()) { InetAddress.getAllByName(hostName); } else { @@ -199,13 +199,13 @@ void testJob() throws IOException, SpallocServerException, Exception { assertTrue(state.getPower()); var chip = new ChipLocation(1, 1); var whereis = client.whereIs(jobId, chip, timeout); - assertEquals(chip, whereis.getJobChip()); - assertEquals(jobId, whereis.getJobId()); + assertEquals(chip, whereis.jobChip()); + assertEquals(jobId, whereis.jobId()); if (client.isActual()) { - assertNotNull(whereis.getBoardChip()); + assertNotNull(whereis.boardChip()); } else { - assertEquals(MockConnectedClient.MOCK_ID, whereis.getJobId()); - assertEquals(chip, whereis.getBoardChip()); + assertEquals(MockConnectedClient.MOCK_ID, whereis.jobId()); + assertEquals(chip, whereis.boardChip()); } client.destroyJob(jobId, "Test finished", timeout); state = client.getJobState(jobId, timeout); @@ -221,7 +221,7 @@ void testVersion() throws IOException, SpallocServerException, Exception { var version = client.version(timeout); if (client.isActual()) { // TODO: Something here! - assertThat("version is meaningful", version.majorVersion, + assertThat("version is meaningful", version.majorVersion(), greaterThan(0)); } else { assertNotNull(version); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java index 1347b189ed..264550e9d7 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java @@ -35,9 +35,9 @@ void testFromJson() throws IOException { var json = "[2, 4, 6]"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, BoardCoordinates.class); - assertEquals(2, fromJson.getX()); - assertEquals(4, fromJson.getY()); - assertEquals(6, fromJson.getZ()); + assertEquals(2, fromJson.x()); + assertEquals(4, fromJson.y()); + assertEquals(6, fromJson.z()); var direct = new BoardCoordinates(2, 4, 6); assertEquals(direct, fromJson); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java index f68f069352..d591b3778e 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java @@ -35,9 +35,9 @@ void testFromJson() throws IOException { var json = "[2, 4, 6]"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, BoardPhysicalCoordinates.class); - assertEquals(2, fromJson.getCabinet()); - assertEquals(4, fromJson.getFrame()); - assertEquals(6, fromJson.getBoard()); + assertEquals(2, fromJson.cabinet()); + assertEquals(4, fromJson.frame()); + assertEquals(6, fromJson.board()); var direct = new BoardPhysicalCoordinates(2, 4, 6); assertEquals(direct, fromJson); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestConnection.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestConnection.java index ef981b50fd..801f05f5e0 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestConnection.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestConnection.java @@ -37,8 +37,8 @@ void testFromJson() throws IOException { var json = "[[2,4],\"6.8.10.12\"]"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, Connection.class); - assertEquals(new ChipLocation(2, 4), fromJson.getChip()); - assertEquals("6.8.10.12", fromJson.getHostname()); + assertEquals(new ChipLocation(2, 4), fromJson.chip()); + assertEquals("6.8.10.12", fromJson.hostname()); var direct = new Connection(new ChipLocation(2, 4), "6.8.10.12"); assertEquals(direct, fromJson); @@ -51,8 +51,8 @@ void testNulls() throws IOException { var json = "[null,null]"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, Connection.class); - assertNull(fromJson.getChip()); - assertNull(fromJson.getHostname()); + assertNull(fromJson.chip()); + assertNull(fromJson.hostname()); var direct = new Connection(null, null); assertEquals(direct, fromJson); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java index f5587f2bbd..a6f9a9aeeb 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java @@ -68,8 +68,8 @@ void testAssumedDeadLinks() throws IOException { assertThat(fromJson.getDeadBoards(), contains( new BoardCoordinates(1, 2, 3), new BoardCoordinates(4, 5, 6))); assertEquals(2, fromJson.getDeadLinks().size()); - assertEquals(7, fromJson.getDeadLinks().get(0).getX()); - assertEquals(14, fromJson.getDeadLinks().get(1).getLink()); + assertEquals(7, fromJson.getDeadLinks().get(0).x()); + assertEquals(14, fromJson.getDeadLinks().get(1).link()); assertNotNull(fromJson.toString()); } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java index 90a5db8ea8..bf9b53d3a3 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java @@ -44,13 +44,13 @@ void testFromJson() throws IOException { + "\"board_chip\":[8,9],\"physical\":[10,11,12]}"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); - assertEquals(jobChip, fromJson.getJobChip()); - assertEquals(666, fromJson.getJobId()); - assertEquals(chip, fromJson.getChip()); - assertEquals(logical, fromJson.getLogical()); - assertEquals("Spin24b-001", fromJson.getMachine()); - assertEquals(boardChip, fromJson.getBoardChip()); - var physical2 = fromJson.getPhysical(); + assertEquals(jobChip, fromJson.jobChip()); + assertEquals(666, fromJson.jobId()); + assertEquals(chip, fromJson.chip()); + assertEquals(logical, fromJson.logical()); + assertEquals("Spin24b-001", fromJson.machine()); + assertEquals(boardChip, fromJson.boardChip()); + var physical2 = fromJson.physical(); assertEquals(physical, physical2); var direct = new WhereIs(jobChip, 666, chip, logical, "Spin24b-001", @@ -72,13 +72,13 @@ void testBug() throws IOException { + "\"board_chip\":[0,0],\"physical\":[0,0,8]}"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.getJobChip()); - assertNull(fromJson.getJobId()); - assertEquals(chip, fromJson.getChip()); - assertEquals(logical, fromJson.getLogical()); - assertEquals("Spin24b-001", fromJson.getMachine()); - assertEquals(boardChip, fromJson.getBoardChip()); - assertEquals(physical, fromJson.getPhysical()); + assertNull(fromJson.jobChip()); + assertNull(fromJson.jobId()); + assertEquals(chip, fromJson.chip()); + assertEquals(logical, fromJson.logical()); + assertEquals("Spin24b-001", fromJson.machine()); + assertEquals(boardChip, fromJson.boardChip()); + assertEquals(physical, fromJson.physical()); var direct = new WhereIs(null, null, chip, logical, "Spin24b-001", boardChip, physical); @@ -95,13 +95,13 @@ void testNulls() throws IOException { + "\"physical\":null}"; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.getJobChip()); - assertNull(fromJson.getJobId()); - assertNull(fromJson.getChip()); - assertNull(fromJson.getLogical()); - assertNull(fromJson.getMachine()); - assertNull(fromJson.getBoardChip()); - assertNull(fromJson.getPhysical()); + assertNull(fromJson.jobChip()); + assertNull(fromJson.jobId()); + assertNull(fromJson.chip()); + assertNull(fromJson.logical()); + assertNull(fromJson.machine()); + assertNull(fromJson.boardChip()); + assertNull(fromJson.physical()); var direct = new WhereIs(null, null, null, null, null, null, null); assertEquals(direct, fromJson); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java index a720b6c074..bb2da832e5 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java @@ -225,30 +225,21 @@ private int countPlacements(List gatherers) { } /** - * Trivial POJO holding the pairing of monitor and list of lists of memory + * Trivial record holding the pairing of monitor and list of lists of memory * blocks. * * @author Donal Fellows + * @param monitor + * Monitor that is used to download the regions. + * @param regions + * List of information about where to download. The inner + * sub-lists are ordered, and are either one or two items long to + * represent what pieces of memory should really be downloaded. + * The outer list could theoretically be done in any order... but + * needs to be processed single-threaded anyway. */ - private static final class WorkItems { - /** - * Monitor that is used to download the regions. - */ - private final Monitor monitor; - - /** - * List of information about where to download. The inner sub-lists are - * ordered, and are either one or two items long to represent what - * pieces of memory should really be downloaded. The outer list could - * theoretically be done in any order... but needs to be processed - * single-threaded anyway. - */ - private final List> regions; - - WorkItems(Monitor m, List> region) { - this.monitor = m; - this.regions = region; - } + private static record WorkItems(Monitor monitor, + List> regions) { } /** @@ -287,7 +278,7 @@ private Map> discoverActualWork( for (var p : m.getPlacements()) { var regions = new ArrayList>(); - for (int id : p.getVertex().getRecordedRegionIds()) { + for (int id : p.vertex().recordedRegionIds()) { var r = getRegion(p, id); if (!r.isEmpty()) { regions.add(r); @@ -401,14 +392,14 @@ private void fastDownload(List work, log.info("processing fast downloads for {}", conn.getChip()); var dl = new Downloader(conn); for (var item : work) { - for (var regionsOnCore : item.regions) { + for (var regionsOnCore : item.regions()) { /* * Once there's something too small, all subsequent * retrieves for that recording region have to be done the * same way to get the data in the DB in the right order. */ for (var region : regionsOnCore) { - var data = dl.doDownload(item.monitor, region); + var data = dl.doDownload(item.monitor(), region); if (SPINNAKER_COMPARE_DOWNLOAD != null) { compareDownloadWithSCP(region, data); } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataReceiver.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataReceiver.java index 7fa7ebe22c..dd9e41eb21 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataReceiver.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataReceiver.java @@ -145,8 +145,8 @@ public void getDataForPlacements(List placements) // get data try (var c = new BoardLocal(placements.get(0))) { for (var placement : placements) { - for (int recordingRegionId : placement.getVertex() - .getRecordedRegionIds()) { + for (int recordingRegionId : placement.vertex() + .recordedRegionIds()) { getDataForPlacement(placement, recordingRegionId); } } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java index 753db829d8..ee0225d585 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java @@ -116,9 +116,9 @@ private IntBuffer getCoreRegionTable(CoreLocation core, Vertex vertex) map = coreTableCache.computeIfAbsent(core, __ -> new HashMap<>()); } // Individual cores are only ever handled from one thread - var buffer = map.get(vertex.getBase()); + var buffer = map.get(vertex.base()); if (buffer == null) { - buffer = txrx.readMemory(core, vertex.getBase(), + buffer = txrx.readMemory(core, vertex.base(), WORD_SIZE * (MAX_MEM_REGIONS + 2)); int word = buffer.getInt(); if (word != APPDATA_MAGIC_NUM) { @@ -130,7 +130,7 @@ private IntBuffer getCoreRegionTable(CoreLocation core, Vertex vertex) throw new IllegalStateException( format("unexpected DSE version: %08x", word)); } - map.put(vertex.getBase(), buffer); + map.put(vertex.base(), buffer); } return buffer.asIntBuffer(); } @@ -139,7 +139,7 @@ private IntBuffer getCoreRegionTable(CoreLocation core, Vertex vertex) protected List getRegion(Placement placement, int regionID) throws IOException, ProcessException, InterruptedException { var b = getCoreRegionTable(placement.asCoreLocation(), - placement.getVertex()); + placement.vertex()); // TODO This is wrong because of shared regions! int size = b.get(regionID + 1) - b.get(regionID); return List.of(new Region(placement, regionID, diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegion.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegion.java index ca755b29c4..5312ccad37 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegion.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegion.java @@ -117,7 +117,7 @@ public String toString() { public static List getRecordingRegionDescriptors( TransceiverInterface txrx, Placement placement) throws IOException, ProcessException, InterruptedException { - var recordingDataAddress = placement.getVertex().getBase(); + var recordingDataAddress = placement.vertex().base(); // Get the size of the list of recordings int nRegions = txrx.readMemory(placement.getScampCore(), recordingDataAddress, WORD_SIZE).getInt(); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Placement.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Placement.java index a570b32355..e376f33cc1 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Placement.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Placement.java @@ -33,9 +33,22 @@ * Vertex placement information. * * @author Christian-B + * @param x + * The X coordinate of the core this vertex is placed on. + * @param y + * The Y coordinate of the core this vertex is placed on. + * @param p + * The processor ID of the core this vertex is placed on. + * @param vertex + * Vertex recording region information. */ @JsonFormat(shape = OBJECT) -public class Placement implements HasCoreLocation { +public record Placement( + @JsonProperty(value = "x", required = true) @ValidX int x, + @JsonProperty(value = "y", required = true) @ValidY int y, + @ValidP @JsonProperty(value = "p", required = true) int p, + @JsonProperty(value = "vertex", required = true) Vertex vertex) + implements HasCoreLocation { /** * Type reference for deserializing a list of placements. */ @@ -44,45 +57,6 @@ public class Placement implements HasCoreLocation { private static class TR extends TypeReference> { } - /** The X coordinate of the core this vertex is placed on. */ - @ValidX - private final int x; - - /** The Y coordinate of the core this vertex is placed on. */ - @ValidY - private final int y; - - /** The processor ID of the core this vertex is placed on. */ - @ValidP - private final int p; - - /** Minimal vertex info. */ - private final Vertex vertex; - - /** - * Constructor with minimum information needed. - *

- * Could be called from an unmarshaller. - * - * @param x - * Vertex X coordinate. - * @param y - * Vertex Y coordinate. - * @param p - * Vertex processor ID. - * @param vertex - * Vertex recording region information. - */ - Placement(@JsonProperty(value = "x", required = true) int x, - @JsonProperty(value = "y", required = true) int y, - @JsonProperty(value = "p", required = true) int p, - @JsonProperty(value = "vertex", required = true) Vertex vertex) { - this.x = x; - this.y = y; - this.p = p; - this.vertex = vertex; - } - @Override public int getX() { return x; @@ -97,9 +71,4 @@ public int getY() { public int getP() { return p; } - - /** @return The information about the vertex. */ - public Vertex getVertex() { - return vertex; - } } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java index 6ae80f87b6..9445a2d3d2 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java @@ -16,8 +16,8 @@ */ package uk.ac.manchester.spinnaker.front_end.download.request; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; import static com.fasterxml.jackson.annotation.JsonFormat.Shape.OBJECT; @@ -31,40 +31,23 @@ * Vertex recording region information. * * @author Christian-B + * @param label + * Label as received from Python. + * @param base + * Address at which to find recording metadata. This was allocated + * during data specification execution, and contains a description of + * all the recording regions owned by a vertex (it may well + * have several, e.g., spikes and voltages). This points to a + * structure that includes the addresses of the per-region metadata, + * and those point in turn to the actual buffers used to do the + * recording (which are circular buffers). + * @param recordedRegionIds + * The recording region IDs that have been actually recorded using + * buffering. */ @JsonFormat(shape = OBJECT) -public class Vertex { - - /** Label as received from Python. */ - private final String label; - - /** - * Address at which to find recording metadata. This was allocated during - * data specification execution, and contains a description of all - * the recording regions owned by a vertex (it may well have several, e.g., - * spikes and voltages). This points to a structure that includes the - * addresses of the per-region metadata, and those point in turn to the - * actual buffers used to do the recording (which are circular - * buffers). - */ - private final long recordingRegionBaseAddress; - - /** - * Address at which to find recording metadata. This was allocated during - * data specification execution, and contains a description of all - * the recording regions owned by a vertex (it may well have several, e.g., - * spikes and voltages). This points to a structure that includes the - * addresses of the per-region metadata, and those point in turn to the - * actual buffers used to do the recording (which are circular - * buffers). - */ - @NotNull - private final MemoryLocation base; - - /** The IDs of the regions recording. */ - @NotNull - private final int[] recordedRegionIds; - +public final record Vertex(String label, @NotNull MemoryLocation base, + @NotNull int[] recordedRegionIds) { /** * Create a minimal vertex, possibly using an unmarshaller. * @@ -77,51 +60,14 @@ public class Vertex { * @param recordedRegionIds * The IDs of the regions doing recording. */ - public Vertex(@JsonProperty(value = "label", required = true) String label, - @JsonProperty(value = "recordingRegionBaseAddress", required = true) - long recordingRegionBaseAddress, - @JsonProperty(value = "recordedRegionIds", required = true) + @JsonCreator + public Vertex(// + @JsonProperty(value = "label", required = true) String label, + @JsonProperty(value = "recordingRegionBaseAddress", // + required = true) long recordingRegionBaseAddress, + @JsonProperty(value = "recordedRegionIds", required = true) // int[] recordedRegionIds) { - this.label = label; - this.recordingRegionBaseAddress = recordingRegionBaseAddress; - this.recordedRegionIds = recordedRegionIds; - this.base = new MemoryLocation(recordingRegionBaseAddress); - } - - /** - * Get the recording region IDs that have been recorded using buffering. - * - * @return The region numbers that have active recording - */ - public int[] getRecordedRegionIds() { - return recordedRegionIds; - } - - /** - * Get the recording region base address. - *

- * Unlike the python this value is cached here. - * - * @return the base address of the recording region - */ - public long getBaseAddress() { - return recordingRegionBaseAddress; - } - - /** - * Get the recording region base address. - * - * @return the base address of the recording region - */ - @JsonIgnore - public MemoryLocation getBase() { - return base; - } - - /** - * @return The label, as received from Python. - */ - public String getLabel() { - return label; + this(label, new MemoryLocation(recordingRegionBaseAddress), + recordedRegionIds); } } diff --git a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/download/TestPlacements.java b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/download/TestPlacements.java index 7624dcfb89..4a7cf03bf3 100644 --- a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/download/TestPlacements.java +++ b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/download/TestPlacements.java @@ -24,6 +24,7 @@ import uk.ac.manchester.spinnaker.front_end.download.request.Placement; import uk.ac.manchester.spinnaker.front_end.download.request.Vertex; +import uk.ac.manchester.spinnaker.machine.MemoryLocation; /** * @@ -35,7 +36,7 @@ public class TestPlacements { public void testVertexJson() throws IOException { var url = TestPlacements.class.getResource("/vertex.json"); var fromJson = createMapper().readValue(url, Vertex.class); - assertEquals(1612972372, fromJson.getBaseAddress()); + assertEquals(new MemoryLocation(1612972372), fromJson.base()); } @Test diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java index e297663184..ff9b0bd5e9 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java @@ -20,34 +20,17 @@ * Wrapper for a board number so that it can't get mixed up with other integers. * * @author Donal Fellows + * @param board + * The board number. */ -public final class BMPBoard { +public final record BMPBoard(@ValidBoardNumber int board) { /** * The maximum board number. There can be only up to 24 boards per frame. */ public static final int MAX_BOARD_NUMBER = 23; - /** The board number. */ - @ValidBoardNumber - public final int board; - - /** @param board The board number. */ - public BMPBoard(int board) { - this.board = board; - } - @Override public String toString() { return "board=" + board; } - - @Override - public int hashCode() { - return board; - } - - @Override - public boolean equals(Object o) { - return (o instanceof BMPBoard b) && (board == b.board); - } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 44f24d165e..9be28a1691 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -48,38 +48,21 @@ *

[c:3,f:2]
* * @author Donal Fellows + * @param cabinet + * The ID of the cabinet that contains the frame that contains the + * BMPs. + * @param frame + * The ID of the frame that contains the master BMP. Frames are + * contained within a cabinet. */ @Immutable @JsonDeserialize(using = BMPCoords.Deserializer.class) -public final class BMPCoords implements Comparable { +public final record BMPCoords(@ValidCabinetNumber int cabinet, + @ValidFrameNumber int frame) implements Comparable { /** Parses the result of {@link #toString()}. */ private static final Pattern PATTERN = Pattern.compile("^\\[c:(\\d+),f:(\\d+)\\]$"); - /** The ID of the cabinet that contains the frame that contains the BMPs. */ - @ValidCabinetNumber - public final int cabinet; - - /** - * The ID of the frame that contains the master BMP. Frames are contained - * within a cabinet. - */ - @ValidFrameNumber - public final int frame; - - /** - * Create an instance. - * - * @param cabinet - * Cabinet number. - * @param frame - * Frame number. - */ - public BMPCoords(int cabinet, int frame) { - this.cabinet = cabinet; - this.frame = frame; - } - /** * Create an instance from its serial form. This is the form produced by * {@link #toString()}. The serial form (where the numbers may vary) is: @@ -94,41 +77,15 @@ public BMPCoords(int cabinet, int frame) { * If the string is not in the right form. */ @JsonCreator - public BMPCoords(String serialForm) { + public static BMPCoords parse(String serialForm) { var m = PATTERN.matcher(serialForm); if (!m.matches()) { throw new IllegalArgumentException("bad argument: " + serialForm); } int idx = 0; - cabinet = parseInt(m.group(++idx)); - frame = parseInt(m.group(++idx)); - } - - /** - * @return The ID of the cabinet that contains the frame that contains the - * BMPs. - */ - public int getCabinet() { - return cabinet; - } - - /** - * @return The ID of the frame that contains the master BMP. Frames are - * contained within a cabinet. - */ - public int getFrame() { - return frame; - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof BMPCoords other) && (cabinet == other.cabinet) - && (frame == other.frame); - } - - @Override - public int hashCode() { - return cabinet * 5 + frame; + int cabinet = parseInt(m.group(++idx)); + int frame = parseInt(m.group(++idx)); + return new BMPCoords(cabinet, frame); } @Override @@ -187,7 +144,7 @@ BMPCoords deserializeObject() throws IOException { @Override BMPCoords deserializeString(String string) { - return new BMPCoords(string); + return BMPCoords.parse(string); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index 6ce7cfdd0d..20a63f8989 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -49,40 +49,20 @@ *
[c:3,f:2,b:1]
* * @author Donal Fellows + * @param c + * Cabinet number. + * @param f + * Frame number. + * @param b + * Board number. */ @Immutable @JsonDeserialize(using = PhysicalCoords.Deserializer.class) -public final class PhysicalCoords implements Comparable { - /** Cabinet number. */ - @ValidCabinetNumber - public final int c; - - /** Frame number. */ - @ValidFrameNumber - public final int f; - - /** Board number. */ - @ValidBoardNumber - public final int b; - - /** - * Create an instance. - * - * @param c - * Cabinet number. - * @param f - * Frame number. - * @param b - * Board number. - */ - @JsonCreator - public PhysicalCoords(@JsonProperty("c") int c, @JsonProperty("f") int f, - @JsonProperty("b") int b) { - this.c = c; - this.f = f; - this.b = b; - } - +public final record PhysicalCoords(// + @JsonProperty("c") @ValidCabinetNumber int c, + @JsonProperty("f") @ValidFrameNumber int f, + @JsonProperty("b") @ValidBoardNumber int b) + implements Comparable { private static final Pattern PATTERN = Pattern.compile("^\\[c:(\\d+),f:(\\d+),b:(\\d+)\\]$"); @@ -100,26 +80,16 @@ public PhysicalCoords(@JsonProperty("c") int c, @JsonProperty("f") int f, * If the string is not in the right form. */ @JsonCreator - public PhysicalCoords(String serialForm) { + public static PhysicalCoords parse(String serialForm) { var m = PATTERN.matcher(serialForm); if (!m.matches()) { throw new IllegalArgumentException("bad argument: " + serialForm); } int idx = 0; - c = parseInt(m.group(++idx)); - f = parseInt(m.group(++idx)); - b = parseInt(m.group(++idx)); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof PhysicalCoords other) && (c == other.c) - && (f == other.f) && (b == other.b); - } - - @Override - public int hashCode() { - return c * 25 + f * 5 + b; + int c = parseInt(m.group(++idx)); + int f = parseInt(m.group(++idx)); + int b = parseInt(m.group(++idx)); + return new PhysicalCoords(c, f, b); } @Override @@ -195,7 +165,7 @@ PhysicalCoords deserializeObject() throws IOException { @Override PhysicalCoords deserializeString(String string) { - return new PhysicalCoords(string); + return PhysicalCoords.parse(string); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index 583d824a93..1d9a5f9635 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -50,9 +50,19 @@ *
[x:3,y:2,z:1]
* * @author Donal Fellows + * @param x + * X coordinate of triad. + * @param y + * Y coordinate of triad. + * @param z + * Z coordinate of triad. */ @JsonDeserialize(using = TriadCoords.Deserializer.class) -public final class TriadCoords implements Comparable { +public final record TriadCoords(// + @JsonProperty("x") @ValidTriadX int x, + @JsonProperty("y") @ValidTriadY int y, + @JsonProperty("z") @ValidTriadZ int z) + implements Comparable { /** The width and height of a triad, in chips. */ private static final int TRIAD_CHIP_SIZE = 12; @@ -64,36 +74,6 @@ public final class TriadCoords implements Comparable { private static final Pattern PATTERN = Pattern.compile("^\\[x:(\\d+),y:(\\d+),z:(\\d+)\\]$"); - /** X coordinate of triad. */ - @ValidTriadX - public final int x; - - /** Y coordinate of triad. */ - @ValidTriadY - public final int y; - - /** Z coordinate of triad. */ - @ValidTriadZ - public final int z; - - /** - * Create an instance. - * - * @param x - * X coordinate. - * @param y - * Y coordinate. - * @param z - * Z coordinate. - */ - @JsonCreator - public TriadCoords(@JsonProperty("x") int x, @JsonProperty("y") int y, - @JsonProperty("z") int z) { - this.x = x; - this.y = y; - this.z = z; - } - /** * Create an instance from its serial form. The serial form (where the * numbers may vary) is: @@ -108,16 +88,17 @@ public TriadCoords(@JsonProperty("x") int x, @JsonProperty("y") int y, * If the string is not in the right form. */ @JsonCreator - public TriadCoords(String serialForm) { + public static TriadCoords parse(String serialForm) { var m = PATTERN.matcher(serialForm); if (!m.matches()) { throw new IllegalArgumentException( "bad argument: " + serialForm); } int idx = 0; - x = parseInt(m.group(++idx)); - y = parseInt(m.group(++idx)); - z = parseInt(m.group(++idx)); + int x = parseInt(m.group(++idx)); + int y = parseInt(m.group(++idx)); + int z = parseInt(m.group(++idx)); + return new TriadCoords(x, y, z); } /** @@ -144,17 +125,6 @@ public ChipLocation asChipLocation() { return new ChipLocation(rootX, rootY); } - @Override - public boolean equals(Object obj) { - return (obj instanceof TriadCoords other) && (x == other.x) - && (y == other.y) && (z == other.z); - } - - @Override - public int hashCode() { - return x * 25 + y * 5 + z; - } - @Override public String toString() { return "[x:" + x + ",y:" + y + ",z:" + z + "]"; @@ -217,7 +187,7 @@ TriadCoords deserializeObject() throws IOException { @Override TriadCoords deserializeString(String string) { - return new TriadCoords(string); + return TriadCoords.parse(string); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java index 6104804d80..3bba906821 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java @@ -17,7 +17,6 @@ package uk.ac.manchester.spinnaker.machine.datalinks; import java.net.InetAddress; -import java.util.Objects; import com.google.errorprone.annotations.Immutable; @@ -25,36 +24,11 @@ * A tuple of an IP address and a SpiNNaker link ID. * * @author Christian-B + * @param address + * The IP address of this tuple, which may be {@code null}. + * @param id + * The ID of this tuple. */ @Immutable -public final class InetIdTuple { - /** The InetAddress of this tuple which may be {@code null}. */ - public final InetAddress address; - - /** The ID of this tuple. */ - public final int id; - - /** - * Make an instance. - * - * @param address - * The IP address of this tuple, which may be {@code null}. - * @param id - * The ID of this tuple. - */ - public InetIdTuple(InetAddress address, int id) { - this.address = address; - this.id = id; - } - - @Override - public int hashCode() { - return Objects.hash(address, id); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof InetIdTuple other) && (id == other.id) - && Objects.equals(address, other.address); - } +public final record InetIdTuple(InetAddress address, int id) { } diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java index da19712146..2762f13fe9 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java @@ -25,8 +25,7 @@ import static java.util.EnumSet.noneOf; import static java.util.Objects.isNull; import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; +import static java.util.stream.Collectors.toUnmodifiableList; import static java.util.stream.Collectors.toUnmodifiableMap; import static java.util.stream.IntStream.range; @@ -122,12 +121,11 @@ public static Function curry(BiFunction fn, */ public static Collection> batch(int batchSize, List input) { - return unmodifiableCollection(range(0, - (input.size() + batchSize - 1) / batchSize) + return range(0, (input.size() + batchSize - 1) / batchSize) .map(i -> i * batchSize) .mapToObj(idx -> unmodifiableCollection( input.subList(idx, min(input.size(), idx + batchSize)))) - .collect(toList())); + .collect(toUnmodifiableList()); } /** @@ -141,27 +139,11 @@ public static Collection> batch(int batchSize, * The input list. * @param fun * How to map an element. - * @return The output list. + * @return The output list. Unmodifiable. */ @UsedInJavadocOnly(Stream.class) public static List lmap(Collection list, Function fun) { - return list.stream().map(fun).collect(toList()); - } - - /** - * Parse a comma-separated string into an unordered set of items. - * - * @param - * The type of elements of the set. - * @param str - * The string to parse. - * @param mapper - * How to get an element from a piece of string. - * @return The set of items. The set is unordered. - */ - public static Set parseCommaSeparatedSet(String str, - Function mapper) { - return stream(str.split(",")).map(mapper).collect(toSet()); + return list.stream().map(fun).collect(toUnmodifiableList()); } /** From cc2dfde471c023b757d3b0ae24e5e0861e4dc679 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 1 Dec 2022 14:02:04 +0000 Subject: [PATCH 015/194] More records --- .../spinnaker/alloc/bmp/FirmwareLoader.java | 4 +- .../spinnaker/alloc/bmp/MockTransceiver.java | 14 ++-- .../uk/ac/manchester/spinnaker/io/FileIO.java | 4 +- .../spinnaker/messages/bmp/BMPReadMemory.java | 2 +- .../messages/bmp/BMPWriteMemory.java | 2 +- .../spinnaker/messages/bmp/EraseFlash.java | 6 +- .../messages/bmp/ReadFPGARegister.java | 2 +- .../messages/bmp/ReadSerialFlash.java | 2 +- .../messages/bmp/ReadSerialFlashCRC.java | 2 +- .../spinnaker/messages/bmp/UpdateFlash.java | 2 +- .../messages/bmp/WriteFPGARegister.java | 2 +- .../messages/bmp/WriteFlashBuffer.java | 2 +- .../messages/bmp/WriteSerialFlash.java | 2 +- .../spinnaker/messages/model/P2PTable.java | 4 +- .../model/SystemVariableDefinition.java | 2 +- .../spinnaker/messages/scp/FillRequest.java | 2 +- .../spinnaker/messages/scp/FloodFillData.java | 4 +- .../spinnaker/messages/scp/ReadLink.java | 4 +- .../spinnaker/messages/scp/ReadMemory.java | 4 +- .../spinnaker/messages/scp/RouterInit.java | 2 +- .../spinnaker/messages/scp/SDRAMDeAlloc.java | 2 +- .../spinnaker/messages/scp/TransferUnit.java | 2 +- .../spinnaker/messages/scp/WriteLink.java | 2 +- .../spinnaker/messages/scp/WriteMemory.java | 4 +- .../transceiver/BMPTransceiverInterface.java | 8 +-- .../spinnaker/transceiver/GetHeapProcess.java | 4 +- .../transceiver/GetMachineProcess.java | 8 +-- .../transceiver/TransceiverInterface.java | 6 +- .../transceiver/TestTransceiver.java | 12 ++-- .../spinnaker/data_spec/Executor.java | 2 +- .../download/StartSendingMessage.java | 2 +- .../front_end/dse/FastDataInProtocol.java | 2 +- .../dse/FastExecuteDataSpecification.java | 2 +- .../dse/HostExecuteDataSpecification.java | 2 +- .../spinnaker/machine/ChipLocation.java | 53 ++++---------- .../spinnaker/machine/CoreLocation.java | 55 +++----------- .../ac/manchester/spinnaker/machine/Link.java | 72 ++----------------- .../manchester/spinnaker/machine/Machine.java | 38 +++++----- .../spinnaker/machine/MachineDimensions.java | 45 +++--------- .../spinnaker/machine/MachineVersion.java | 28 ++++---- .../spinnaker/machine/MemoryLocation.java | 20 +++--- .../spinnaker/machine/NeighbourIterator.java | 2 +- .../manchester/spinnaker/machine/Router.java | 12 ++-- .../machine/SpiNNakerTriadGeometry.java | 12 ++-- .../spinnaker/machine/bean/ChipBean.java | 4 +- .../spinnaker/machine/bean/ChipDetails.java | 4 +- .../spinnaker/machine/bean/LinkBean.java | 21 +++--- .../spinnaker/machine/bean/MachineBean.java | 69 ++++++------------ .../spinnaker/machine/TestVirtualMachine.java | 2 +- .../machine/bean/TestMachineBean.java | 4 +- .../storage/sqlite/SQLiteBufferStorage.java | 2 +- .../storage/sqlite/SQLiteDataSpecStorage.java | 2 +- 52 files changed, 191 insertions(+), 380 deletions(-) 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 2d58b929ad..a820319d49 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 @@ -274,7 +274,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); @@ -504,7 +504,7 @@ 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.address().address() | r.fpga().value); data.add(r.value()); } var sector = FlashDataSector.registers(settings.length, data); 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 b2f691f49f..868cba31a2 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 @@ -199,8 +199,8 @@ public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, length); // Pad to length - var b = flash.slice(baseAddress.address, length).order(LITTLE_ENDIAN); - 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); } @@ -211,7 +211,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 memory.slice(baseAddress.address, length).order(LITTLE_ENDIAN); + return memory.slice(baseAddress.address(), length).order(LITTLE_ENDIAN); } @Override @@ -225,7 +225,7 @@ public void writeBMPMemory(BMPCoords bmp, BMPBoard board, MemoryLocation baseAddress, ByteBuffer data) { log.info("writeBMPMemory({},{},{}:{})", bmp, board, baseAddress, data.remaining()); - memory.slice(baseAddress.address, data.remaining()) + memory.slice(baseAddress.address(), data.remaining()) .put(data.duplicate()); } @@ -250,7 +250,7 @@ public void writeSerialFlash(BMPCoords bmp, BMPBoard board, MemoryLocation baseAddress, ByteBuffer data) { log.info("writeSerialFlash({},{},{}:{})", bmp, board, baseAddress, data.remaining()); - var b = flash.slice(baseAddress.address, data.remaining()) + var b = flash.slice(baseAddress.address(), data.remaining()) .order(LITTLE_ENDIAN).put(data); b.position(SERIAL_FLASH_BLACKLIST_OFFSET); var bl = new Blacklist(b); @@ -269,7 +269,7 @@ public void writeSerialFlash(BMPCoords bmp, BMPBoard board, throws IOException { log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress, size); - flash.slice(baseAddress.address, size).put(readFully(stream, size)); + flash.slice(baseAddress.address(), size).put(readFully(stream, size)); } @Override @@ -286,7 +286,7 @@ public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board, log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress, length); var crc = new CRC32(); - crc.update(flash.slice(baseAddress.address, length)); + crc.update(flash.slice(baseAddress.address(), length)); return (int) (crc.getValue() & CRC_MASK); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/FileIO.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/FileIO.java index 88310a3da5..563c431405 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/FileIO.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/FileIO.java @@ -107,7 +107,7 @@ public void flush() { byte[] doRead(int numBytes) throws IOException { var data = new byte[numBytes]; synchronized (file) { - file.seek(current.address); + file.seek(current.address()); file.readFully(data, 0, numBytes); } return data; @@ -116,7 +116,7 @@ byte[] doRead(int numBytes) throws IOException { @Override void doWrite(byte[] data, int from, int len) throws IOException { synchronized (file) { - file.seek(current.address); + file.seek(current.address()); file.write(data, from, len); } } 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/BMPReadMemory.java index 9be1ecb07e..7c5e578ad7 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/BMPReadMemory.java @@ -46,7 +46,7 @@ private static int validate(int 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), + super(board, CMD_READ, address.address(), validate(size), efficientTransferUnit(address, size).value); } 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/BMPWriteMemory.java index c406661533..99525ec7ef 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/BMPWriteMemory.java @@ -39,7 +39,7 @@ public class BMPWriteMemory extends BMPRequest { */ public BMPWriteMemory(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/EraseFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/EraseFlash.java index 096c1374d1..82e9905ed4 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 @@ -42,13 +42,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/ReadFPGARegister.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadFPGARegister.java index a963607a89..8a5dca44d3 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 @@ -43,7 +43,7 @@ public class ReadFPGARegister extends BMPRequest { */ public ReadFPGARegister(FPGA fpga, MemoryLocation register, BMPBoard board) { - super(board, CMD_LINK_READ, register.address, WORD_SIZE, fpga.value); + super(board, CMD_LINK_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/ReadSerialFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java index 781f5c0ddd..fe5588b357 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 @@ -45,7 +45,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), 0); + super(board, CMD_BMP_SF, address.address(), validate(size), 0); } @Override 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 d4fb38671d..affe94d1b1 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 @@ -39,7 +39,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/UpdateFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/UpdateFlash.java index ad1dc47ea8..285be45ba6 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 @@ -39,7 +39,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/WriteFPGARegister.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java index caf2febaa8..e2f26e32f4 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 @@ -52,7 +52,7 @@ public class WriteFPGARegister extends BMPRequest { */ public WriteFPGARegister(FPGA fpga, MemoryLocation register, int value, BMPBoard board) { - super(board, CMD_LINK_WRITE, register.address, WORD_SIZE, fpga.value, + super(board, CMD_LINK_WRITE, register.address(), WORD_SIZE, fpga.value, data(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 8196507e64..64ba3c149b 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 @@ -41,7 +41,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 8d86c95184..ed4514a539 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 @@ -44,7 +44,7 @@ public class WriteSerialFlash extends BMPRequest { */ public WriteSerialFlash(BMPBoard board, MemoryLocation baseAddress, ByteBuffer data) { - super(board, CMD_BMP_SF, baseAddress.address, FLASH_CHUNK_SIZE, + super(board, CMD_BMP_SF, baseAddress.address(), FLASH_CHUNK_SIZE, WRITE.value, limitSlice(data, FLASH_CHUNK_SIZE)); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java index 199180352e..2b7ac7e44e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java @@ -68,8 +68,8 @@ public class P2PTable { public P2PTable(MachineDimensions dimensions, Collection columnData) { this.routes = new HashMap<>(); - this.width = dimensions.width; - this.height = dimensions.height; + this.width = dimensions.width(); + this.height = dimensions.height(); parseColumnData(columnData); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java index 1615d5866f..e157920162 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java @@ -338,7 +338,7 @@ public void addToBuffer(Object value, ByteBuffer buffer) { buffer.put((byte[]) value); return; case ADDRESS: - buffer.putInt(((MemoryLocation) value).address); + buffer.putInt(((MemoryLocation) value).address()); return; default: // CHECKSTYLE:OFF diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FillRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FillRequest.java index 3d984d26b5..a64f98b3bf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FillRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FillRequest.java @@ -37,7 +37,7 @@ public final class FillRequest extends SCPRequest { */ public FillRequest(HasChipLocation chip, MemoryLocation baseAddress, int data, int size) { - super(chip.getScampCore(), CMD_FILL, baseAddress.address, data, size); + super(chip.getScampCore(), CMD_FILL, baseAddress.address(), data, size); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java index c1dc6b0c48..e05421d9c0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java @@ -72,7 +72,7 @@ public FloodFillData(byte nearestNeighbourID, int blockNumber, public FloodFillData(byte nearestNeighbourID, int blockNumber, MemoryLocation baseAddress, byte[] data, int offset, int length) { super(BOOT_MONITOR_CORE, CMD_FFD, argument1(nearestNeighbourID), - argument2(blockNumber, length), baseAddress.address, + argument2(blockNumber, length), baseAddress.address(), wrap(data, offset, length)); } @@ -92,7 +92,7 @@ public FloodFillData(byte nearestNeighbourID, int blockNumber, public FloodFillData(byte nearestNeighbourID, int blockNumber, MemoryLocation baseAddress, ByteBuffer data) { super(BOOT_MONITOR_CORE, CMD_FFD, argument1(nearestNeighbourID), - argument2(blockNumber, data.remaining()), baseAddress.address, + argument2(blockNumber, data.remaining()), baseAddress.address(), data); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java index 204479f1b1..08587cf315 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java @@ -50,7 +50,7 @@ private static int validate(int size) { */ public ReadLink(HasCoreLocation core, Direction link, MemoryLocation baseAddress, int size) { - super(core, CMD_LINK_READ, baseAddress.address, validate(size), + super(core, CMD_LINK_READ, baseAddress.address(), validate(size), link.id); } @@ -66,7 +66,7 @@ public ReadLink(HasCoreLocation core, Direction link, */ public ReadLink(HasChipLocation chip, Direction link, MemoryLocation baseAddress, int size) { - super(chip.getScampCore(), CMD_LINK_READ, baseAddress.address, + super(chip.getScampCore(), CMD_LINK_READ, baseAddress.address(), validate(size), link.id); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java index 2a9dca11e0..35574fc2de 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java @@ -47,7 +47,7 @@ private static int validate(int size) { * The number of bytes to read, between 1 and 256 */ public ReadMemory(HasCoreLocation core, MemoryLocation address, int size) { - super(core, CMD_READ, address.address, validate(size), + super(core, CMD_READ, address.address(), validate(size), efficientTransferUnit(address, size).value); } @@ -60,7 +60,7 @@ public ReadMemory(HasCoreLocation core, MemoryLocation address, int size) { * The number of bytes to read, between 1 and 256 */ public ReadMemory(HasChipLocation chip, MemoryLocation address, int size) { - super(chip.getScampCore(), CMD_READ, address.address, validate(size), + super(chip.getScampCore(), CMD_READ, address.address(), validate(size), efficientTransferUnit(address, size).value); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java index a0744ef00c..ec87ee868c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java @@ -52,7 +52,7 @@ public RouterInit(HasChipLocation chip, int numEntries, MemoryLocation tableAddress, int baseIndex, AppID appID) { super(chip.getScampCore(), CMD_RTR, argument1(numEntries, appID), - tableAddress.address, baseIndex); + tableAddress.address(), baseIndex); if (baseIndex < 0) { throw new IllegalArgumentException( "baseIndex must not be negative"); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java index 5b8e21d808..f43cb31688 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java @@ -57,7 +57,7 @@ public SDRAMDeAlloc(HasChipLocation chip, AppID appID) { */ public SDRAMDeAlloc(HasChipLocation chip, MemoryLocation baseAddress) { super(chip.getScampCore(), CMD_ALLOC, FREE_SDRAM_BY_POINTER.value, - baseAddress.address); + baseAddress.address()); readNumFreedBlocks = false; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/TransferUnit.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/TransferUnit.java index 44f4231dc6..142bfd07c8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/TransferUnit.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/TransferUnit.java @@ -63,7 +63,7 @@ public static TransferUnit efficientTransferUnit(MemoryLocation address, int size) { if (address.isAligned() && size % WORD_SIZE == 0) { return WORD; - } else if (odd(address.address) || odd(size)) { + } else if (odd(address.address()) || odd(size)) { return BYTE; } else { return HALF_WORD; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java index c90bc8f633..f5cdbdf7b6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java @@ -41,7 +41,7 @@ public class WriteLink extends SCPRequest { */ public WriteLink(HasCoreLocation core, Direction link, MemoryLocation baseAddress, ByteBuffer data) { - super(core, CMD_LINK_WRITE, baseAddress.address, data.remaining(), + super(core, CMD_LINK_WRITE, baseAddress.address(), data.remaining(), link.id, data); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java index 720baa2f7b..6fada07a3b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java @@ -40,7 +40,7 @@ public class WriteMemory extends SCPRequest { */ public WriteMemory(HasCoreLocation core, MemoryLocation baseAddress, ByteBuffer data) { - super(core, CMD_WRITE, baseAddress.address, data.remaining(), + super(core, CMD_WRITE, baseAddress.address(), data.remaining(), efficientTransferUnit(baseAddress, data.remaining()).value, data); } @@ -58,7 +58,7 @@ public WriteMemory(HasCoreLocation core, MemoryLocation baseAddress, */ public WriteMemory(HasChipLocation chip, MemoryLocation baseAddress, ByteBuffer data) { - super(chip.getScampCore(), CMD_WRITE, baseAddress.address, + super(chip.getScampCore(), CMD_WRITE, baseAddress.address(), data.remaining(), efficientTransferUnit(baseAddress, data.remaining()).value, data); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java index 6e52ba5a18..50b4ea50b8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java @@ -1539,11 +1539,11 @@ default void writeBlacklist(@Valid BMPCoords bmp, @Valid BMPBoard board, } // Prepare the serial flash update; must read part of the data first - var sfData = new byte[SF_BL_ADDR.address + SF_BL_LEN]; - readSerialFlash(bmp, board, NULL, SF_BL_ADDR.address).get(sfData, 0, - SF_BL_ADDR.address); + var sfData = new byte[SF_BL_ADDR.address() + SF_BL_LEN]; + readSerialFlash(bmp, board, NULL, SF_BL_ADDR.address()).get(sfData, 0, + SF_BL_ADDR.address()); data.position(BMP_BOOT_BLACKLIST_OFFSET); - data.get(sfData, SF_BL_ADDR.address, SF_BL_LEN); + data.get(sfData, SF_BL_ADDR.address(), SF_BL_LEN); data.position(0); // Prep for write diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java index b48c947bcd..761f249069 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java @@ -83,7 +83,7 @@ List getBlocks(HasChipLocation chip, var block = getBlockHeader(chip, nextBlock); if (!block.next.isNull()) { blocks.add(new HeapElement(nextBlock, block.next, - block.free.address)); + block.free.address())); } nextBlock = block.next; } @@ -120,7 +120,7 @@ List getFreeBlocks(HasChipLocation chip, var block = getBlockHeader(chip, nextBlock); if (!block.next.isNull()) { blocks.add(new HeapElement(nextBlock, block.next, - block.free.address)); + block.free.address())); } nextBlock = block.free; } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java index ce080ecc9a..06007c16e1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java @@ -136,10 +136,10 @@ Machine getMachineDetails(HasChipLocation bootChip, MachineDimensions size) throws IOException, ProcessException, InterruptedException { // Get the P2P table; 8 entries are packed into each 32-bit word var p2pColumnData = new ArrayList(); - for (int column = 0; column < size.width; column++) { + for (int column = 0; column < size.width(); column++) { p2pColumnData.add(synchronousCall(new ReadMemory(bootChip, ROUTER_P2P.add(getColumnOffset(column)), - getNumColumnBytes(size.height))).data); + getNumColumnBytes(size.height()))).data); // TODO work out why multiple calls at once is a problem } var p2pTable = new P2PTable(size, p2pColumnData); @@ -249,8 +249,8 @@ private List makeLinks(ChipSummaryInfo chipInfo, private static ChipLocation getChipOverLink(HasChipLocation chip, MachineDimensions size, Direction link) { /// TODO CHECK negative wraparound! - int x = (chip.getX() + link.xChange + size.width) % size.width; - int y = (chip.getY() + link.yChange + size.height) % size.height; + int x = (chip.getX() + link.xChange + size.width()) % size.width(); + int y = (chip.getY() + link.yChange + size.height()) % size.height(); return new ChipLocation(x, y); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java index a1a102f05f..05409739dc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java @@ -1858,7 +1858,7 @@ default void writeUser0(@Valid HasCoreLocation core, @NotNull MemoryLocation pointer) throws ProcessException, IOException, InterruptedException { writeMemory(core.getScampCore(), getUser0RegisterAddress(core), - pointer.address); + pointer.address()); } /** @@ -1899,7 +1899,7 @@ default void writeUser1(@Valid HasCoreLocation core, @NotNull MemoryLocation pointer) throws ProcessException, IOException, InterruptedException { writeMemory(core.getScampCore(), getUser1RegisterAddress(core), - pointer.address); + pointer.address()); } /** @@ -1940,7 +1940,7 @@ default void writeUser2(@Valid HasCoreLocation core, @NotNull MemoryLocation pointer) throws ProcessException, IOException, InterruptedException { writeMemory(core.getScampCore(), getUser2RegisterAddress(core), - pointer.address); + pointer.address()); } /** diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TestTransceiver.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TestTransceiver.java index cfa8ace8b2..56e5db8d55 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TestTransceiver.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TestTransceiver.java @@ -123,15 +123,15 @@ void testRetrievingMachineDetails() throws Exception { try (var txrx = new Transceiver(FIVE, connections, null, null, null, null, null)) { if (boardConfig.boardVersion.isFourChip) { - assertEquals(2, txrx.getMachineDimensions().width); - assertEquals(2, txrx.getMachineDimensions().height); + assertEquals(2, txrx.getMachineDimensions().width()); + assertEquals(2, txrx.getMachineDimensions().height()); } else if (boardConfig.boardVersion.isFourtyeightChip) { - assertEquals(8, txrx.getMachineDimensions().width); - assertEquals(8, txrx.getMachineDimensions().height); + assertEquals(8, txrx.getMachineDimensions().width()); + assertEquals(8, txrx.getMachineDimensions().height()); } else { var size = txrx.getMachineDimensions(); - fail(format("Unknown board with size %dx%d", size.width, - size.height)); + fail(format("Unknown board with size %dx%d", size.width(), + size.height())); } assertTrue(txrx.isConnected()); assertNotNull(txrx.getScampVersion()); diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java index b649e77568..efa7b5b5a0 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java @@ -214,7 +214,7 @@ public void addPointerTable(ByteBuffer buffer) { assert buffer.order() == LITTLE_ENDIAN; for (var reg : memRegions) { if (reg != null) { - buffer.putInt(reg.getRegionBase().address); + buffer.putInt(reg.getRegionBase().address()); if (reg instanceof MemoryRegionReal regReal) { // Work out the checksum int nWords = diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java index 58ee72b24e..6f5f409724 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java @@ -52,7 +52,7 @@ static StartSendingMessage create(HasCoreLocation destination, var payload = allocate(NUM_WORDS * WORD_SIZE).order(LITTLE_ENDIAN); payload.putInt(START_SENDING_DATA.value); payload.putInt(transactionId); - payload.putInt(address.address); + payload.putInt(address.address()); payload.putInt(length); payload.flip(); return new StartSendingMessage(destination, payload); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java index 91a93b0972..553233aa57 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java @@ -125,7 +125,7 @@ SDPMessage dataToLocation(MemoryLocation baseAddress, int numPackets, var payload = allocate(BYTES_FOR_LOCATION_PACKET).order(LITTLE_ENDIAN); payload.putInt(SEND_DATA_TO_LOCATION.value); payload.putInt(transactionId); - payload.putInt(baseAddress.address); + payload.putInt(baseAddress.address()); payload.putShort((short) boardLocalDestination.getY()); payload.putShort((short) boardLocalDestination.getX()); payload.putInt(numPackets - 1); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index b126f47b6f..4ed5ee3976 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -228,7 +228,7 @@ private void loadBoard(Ethernet board, DSEStorage storage, Progress bar) var addresses = new HashMap(); for (var ctl : cores) { var start = malloc(ctl, ctl.sizeToWrite); - txrx.writeUser0(ctl.core, start.address); + txrx.writeUser0(ctl.core, start.address()); addresses.put(ctl, start); } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java index a7fe2f68b8..d4c61b7e9b 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java @@ -279,7 +279,7 @@ void loadCore(CoreToLoad ctl) throws IOException, ProcessException, } } - txrx.writeUser0(ctl.core, start.address); + txrx.writeUser0(ctl.core, start.address()); bar.update(); storage.saveLoadingMetadata(ctl, start, size, written); } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java index 48d7db127f..51d012540c 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ChipLocation.java @@ -16,47 +16,35 @@ */ package uk.ac.manchester.spinnaker.machine; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; import static java.lang.Integer.compare; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.COORD_SHIFT; import static uk.ac.manchester.spinnaker.machine.MachineDefaults.validateChipLocation; import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.errorprone.annotations.Immutable; /** * The location of a Chip as an X and Y tuple. - *

- * This class is final as it is used a key in maps. * * @author alan * @author dkf + * @param x + * The X coordinate. + * @param y + * The Y coordinate. */ @Immutable @JsonFormat(shape = ARRAY) -/* - * This is needed in Java 8, but not by Java 10 (which can find the @JsonIgnore - * annotation on the default property all by itself. - */ -@JsonIgnoreProperties({"scamp-core", "scamp_core", "scampCore"}) -public final class ChipLocation +@JsonIgnoreProperties({ "scamp-core", "scamp_core", "scampCore" }) +public record ChipLocation( + @JsonProperty(value = "x", required = true) @ValidX int x, + @JsonProperty(value = "y", required = true) @ValidY int y) implements HasChipLocation, Comparable, Serializable { - private static final long serialVersionUID = -2343484354316378507L; - - /** The X coordinate. */ - @ValidX - private final int x; - - /** The Y coordinate. */ - @ValidY - private final int y; - /** * The location (0,0), which is in the bottom/left corner and typically the * ethernet chip for the lead board of an allocation. @@ -82,25 +70,8 @@ public final class ChipLocation * Thrown is either x or y is negative or too big. */ @JsonCreator - public ChipLocation(@JsonProperty(value = "x", required = true) int x, - @JsonProperty(value = "y", required = true) int y) { + public ChipLocation { validateChipLocation(x, y); - this.x = x; - this.y = y; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - return (obj instanceof ChipLocation that) && (x == that.x) - && (y == that.y); - } - - @Override - public int hashCode() { - return (x << COORD_SHIFT) ^ y; } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java index 464faccdf0..96363f8e58 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreLocation.java @@ -17,8 +17,6 @@ package uk.ac.manchester.spinnaker.machine; import static java.lang.Integer.compare; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.COORD_SHIFT; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.CORE_SHIFT; import static uk.ac.manchester.spinnaker.machine.MachineDefaults.validateCoreLocation; import java.io.Serializable; @@ -27,44 +25,21 @@ /** * The location of a Core as an X, Y, P tuple. - *

- * This class is final as it is used a key in maps. * * @author alan * @author dkf + * @param x + * The X coordinate, in range 0..255 + * @param y + * The Y coordinate, in range 0..255 + * @param p + * The P coordinate, in range 0..17 */ @Immutable -public final class CoreLocation +public record CoreLocation(@ValidX int x, @ValidY int y, @ValidP int p) implements HasCoreLocation, Comparable, Serializable { - private static final long serialVersionUID = 2930811082362121057L; - - /** The X coordinate. */ - @ValidX - private final int x; - - /** The Y coordinate. */ - @ValidY - private final int y; - - /** The P coordinate. */ - @ValidP - private final int p; - - /** - * Create the location of a core on a SpiNNaker machine. - * - * @param x - * The X coordinate, in range 0..255 - * @param y - * The Y coordinate, in range 0..255 - * @param p - * The P coordinate, in range 0..17 - */ - public CoreLocation(int x, int y, int p) { + public CoreLocation { validateCoreLocation(x, y, p); - this.x = x; - this.y = y; - this.p = p; } /** @@ -79,20 +54,6 @@ public CoreLocation(HasChipLocation chip, int p) { this(chip.getX(), chip.getY(), p); } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - return (obj instanceof CoreLocation that) && (x == that.x) - && (y == that.y) && (p == that.p); - } - - @Override - public int hashCode() { - return (((x << COORD_SHIFT) ^ y) << CORE_SHIFT) ^ p; - } - @Override public int getX() { return x; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java index 1bb1db6ad6..f6620b0190 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java @@ -16,15 +16,8 @@ */ package uk.ac.manchester.spinnaker.machine; -import static java.util.Objects.hash; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Objects; - import javax.validation.Valid; -import org.slf4j.Logger; - import com.google.errorprone.annotations.Immutable; /** @@ -34,50 +27,15 @@ * "https://github.com/SpiNNakerManchester/SpiNNMachine/blob/master/spinn_machine/link.py"> * Python Version * @author Christian-B + * @param source The coordinates of the source chip of the link. + * @param sourceLinkDirection The direction of the link in the source chip. + * @param destination The coordinate of the destination chip of the link. */ @Immutable -public final class Link { - private static final Logger log = getLogger(Link.class); - - /** The coordinates of the source chip of the link. */ - @Valid - public final ChipLocation source; - - /** The ID/Direction of the link in the source chip. */ - public final Direction sourceLinkDirection; - - /** The coordinate of the destination chip of the link. */ - @Valid - public final ChipLocation destination; - +public final record Link(@Valid ChipLocation source, + Direction sourceLinkDirection, @Valid ChipLocation destination) { // Note: multicast_default_from and multicast_default_to not implemented - - /** - * Main Constructor which sets all parameters. - *

- * Specifically there is no check that the destination is the - * typical one for this source and direction pair. - * - * @param source - * The coordinates of the source chip of the link. - * @param destination - * The coordinate of the destination chip of the link. - * @param sourceLinkDirection - * The Direction of the link in the source chip. - */ - public Link(ChipLocation source, Direction sourceLinkDirection, - ChipLocation destination) { - this.source = source; - this.sourceLinkDirection = sourceLinkDirection; - this.destination = destination; - } - /** - * Main Constructor which sets all parameters. - *

- * Specifically there is no check that the destination is the - * typical one for this source and direction pair. - * * @param source * The coordinates of the source chip of the link. * @param destination @@ -91,11 +49,6 @@ public Link(HasChipLocation source, Direction sourceLinkDirection, destination.asChipLocation()); } - @Override - public int hashCode() { - return hash(source, sourceLinkDirection, destination); - } - /** * @param source * The coordinates of the source chip of the link. @@ -109,21 +62,6 @@ public Link(HasChipLocation source, int sourceLinkId, this(source, Direction.byId(sourceLinkId), destination); } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (!(obj instanceof Link other)) { - return false; - } - log.trace("Equals called {} {}", this, other); - if (sourceLinkDirection != other.sourceLinkDirection) { - return false; - } - return Objects.equals(source, other.source) - && Objects.equals(destination, other.destination); - } - @Override public String toString() { return "Link{" + "source=" + source + ", source_link_id=" diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java index 8d3d5ef7f6..2e70113ed3 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java @@ -147,8 +147,8 @@ public Machine(MachineDimensions machineDimensions, Iterable chips, * Bean holding the Values to set. */ public Machine(MachineBean bean) { - this(bean.getMachineDimensions(), bean.getRoot()); - for (var chipBean : bean.getChips()) { + this(bean.dimensions(), bean.root()); + for (var chipBean : bean.chips()) { chipBean.addDefaults(bean); addChip(new Chip(chipBean, this)); } @@ -226,9 +226,9 @@ public Machine rebuild(Set ignoreChips, var downDirections = ignoreLinks.get(location); var links = new ArrayList(); for (var link : chip.router) { - if (downDirections.contains(link.sourceLinkDirection)) { + if (downDirections.contains(link.sourceLinkDirection())) { log.info("Rebuilt machine without Link {} {}", - location, link.sourceLinkDirection); + location, link.sourceLinkDirection()); } else { links.add(link); } @@ -257,15 +257,15 @@ public final void addChip(Chip chip) { "There is already a Chip at location: " + location); } - if (chip.getX() >= machineDimensions.width) { + if (chip.getX() >= machineDimensions.width()) { throw new IllegalArgumentException("Chip x: " + chip.getX() + " is too high for a machine with width " - + machineDimensions.width); + + machineDimensions.width()); } - if (chip.getY() >= machineDimensions.height) { + if (chip.getY() >= machineDimensions.height()) { throw new IllegalArgumentException("Chip y: " + chip.getY() + " is too high for a machine with height " - + machineDimensions.height + " " + chip); + + machineDimensions.height() + " " + chip); } chips.put(location, chip); @@ -505,7 +505,7 @@ public final Chip getChipOverLink(HasChipLocation source, * @return The maximum possible x-coordinate. */ public final int maxChipX() { - return machineDimensions.width - 1; + return machineDimensions.width() - 1; } /** @@ -517,7 +517,7 @@ public final int maxChipX() { * @return The maximum possible y-coordinate. */ public final int maxChipY() { - return machineDimensions.height - 1; + return machineDimensions.height() - 1; } /** @@ -628,13 +628,13 @@ public final void addSpinnakerLinks() { */ public final ChipLocation normalizedLocation(int x, int y) { if (version.horizontalWrap) { - x = (x + machineDimensions.width) % machineDimensions.width; - } else if (x < 0 || x >= machineDimensions.width) { + x = (x + machineDimensions.width()) % machineDimensions.width(); + } else if (x < 0 || x >= machineDimensions.width()) { return null; } if (version.verticalWrap) { - y = (y + machineDimensions.height) % machineDimensions.height; - } else if (y < 0 || y >= machineDimensions.height) { + y = (y + machineDimensions.height()) % machineDimensions.height(); + } else if (y < 0 || y >= machineDimensions.height()) { return null; } if (x < 0 || y < 0) { @@ -903,14 +903,14 @@ public Map> findAbnormalLinks() { * rules, it's considered to be normal. Everything else is * abnormal. */ - if (hasChipAt(link.destination) - && getChipAt(link.destination).router - .hasLink(link.sourceLinkDirection.inverse())) { + if (hasChipAt(link.destination()) + && getChipAt(link.destination()).router.hasLink( + link.sourceLinkDirection().inverse())) { continue; } abnormalLinks - .computeIfAbsent(link.source, __ -> new HashSet<>()) - .add(link.sourceLinkDirection); + .computeIfAbsent(link.source(), __ -> new HashSet<>()) + .add(link.sourceLinkDirection()); } } return unmodifiableMap(abnormalLinks); diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java index 1160698048..0f4e5e7b81 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineDimensions.java @@ -18,41 +18,18 @@ import com.google.errorprone.annotations.Immutable; -/** Represents the size of a machine in chips. */ +/** + * Represents the size of a machine in chips. + * + * @param width + * The width of the machine, in chips. + * @param height + * The height of the machine, in chips. + */ @Immutable -public final class MachineDimensions { - /** The width of the machine in chips. */ - @ValidMachineWidth - public final int width; - - /** The height of the machine in chips. */ - @ValidMachineHeight - public final int height; - - /** - * Create a new instance. - * - * @param width - * The width of the machine, in chips. - * @param height - * The height of the machine, in chips. - */ - public MachineDimensions(int width, int height) { - this.width = width; - this.height = height; - } - - @Override - public boolean equals(Object o) { - return (o instanceof MachineDimensions dim) && (width == dim.width) - && (height == dim.height); - } - - @Override - public int hashCode() { - return width << 16 | height; - } - +public record MachineDimensions(// + @ValidMachineWidth int width, // + @ValidMachineHeight int height) { @Override public String toString() { return "Width:" + width + " Height:" + height; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineVersion.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineVersion.java index c63b956e88..4a80807f5a 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineVersion.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MachineVersion.java @@ -280,17 +280,17 @@ public static MachineVersion bySize(MachineDimensions dimensions) { return possible; } } - if ((dimensions.width % TRIAD_HEIGHT == 0) - && (dimensions.height % TRIAD_WIDTH == 0)) { + if ((dimensions.width() % TRIAD_HEIGHT == 0) + && (dimensions.height() % TRIAD_WIDTH == 0)) { return TRIAD_WITH_WRAPAROUND; } - if (((dimensions.width - HALF_SIZE) % TRIAD_HEIGHT == 0) - && ((dimensions.height - HALF_SIZE) % TRIAD_WIDTH == 0)) { + if (((dimensions.width() - HALF_SIZE) % TRIAD_HEIGHT == 0) + && ((dimensions.height() - HALF_SIZE) % TRIAD_WIDTH == 0)) { return TRIAD_NO_WRAPAROUND; } // Handle 4 chip board extended with virtual_chips - if (dimensions.width < SIZE_X_OF_ONE_BOARD) { - if (dimensions.height < SIZE_Y_OF_ONE_BOARD) { + if (dimensions.width() < SIZE_X_OF_ONE_BOARD) { + if (dimensions.height() < SIZE_Y_OF_ONE_BOARD) { return EXTENDED_SMALL; } } @@ -299,22 +299,22 @@ public static MachineVersion bySize(MachineDimensions dimensions) { * three board toroid we need at least two board on top of each other or * next to each other */ - if (dimensions.width < SIZE_X_OF_ONE_BOARD * 2) { - if (dimensions.height < SIZE_Y_OF_ONE_BOARD * 2) { + if (dimensions.width() < SIZE_X_OF_ONE_BOARD * 2) { + if (dimensions.height() < SIZE_Y_OF_ONE_BOARD * 2) { throw new IllegalArgumentException( "Dimensions " + dimensions + "too small!"); } } - if ((dimensions.width % TRIAD_HEIGHT == 0) - && ((dimensions.height - HALF_SIZE) % TRIAD_WIDTH == 0)) { + if ((dimensions.width() % TRIAD_HEIGHT == 0) + && ((dimensions.height() - HALF_SIZE) % TRIAD_WIDTH == 0)) { return TRIAD_WITH_HORIZONTAL_WRAP; } - if (((dimensions.width - HALF_SIZE) % TRIAD_HEIGHT == 0) - && (dimensions.height % TRIAD_WIDTH == 0)) { + if (((dimensions.width() - HALF_SIZE) % TRIAD_HEIGHT == 0) + && (dimensions.height() % TRIAD_WIDTH == 0)) { return TRIAD_WITH_VERTICAL_WRAP; } - if (dimensions.width % HALF_SIZE == 0 - && dimensions.height % HALF_SIZE == 0) { + if (dimensions.width() % HALF_SIZE == 0 + && dimensions.height() % HALF_SIZE == 0) { return NONE_TRIAD_LARGE; } throw new IllegalArgumentException("Dimensions " + dimensions diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java index fcc8936a87..7ed36f2527 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java @@ -26,26 +26,24 @@ * is in. * * @author Donal Fellows + * @param address + * The actual location. */ @Immutable -public final class MemoryLocation implements Comparable { +public record MemoryLocation(int address) + implements Comparable { /** Number of bytes in a SpiNNaker (ARM) word. */ private static final int WORD_SIZE = 4; /** The zero memory location. Often means "no actual address". */ public static final MemoryLocation NULL = new MemoryLocation(0); - /** The actual location. */ - public final int address; - - /** @param address The actual location. */ - public MemoryLocation(int address) { - this.address = address; - } - - /** @param address The actual location. */ + /** + * @param address + * The actual location. + */ public MemoryLocation(long address) { - this.address = convert(address); + this(convert(address)); } /** diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/NeighbourIterator.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/NeighbourIterator.java index a735597275..799c06ed4b 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/NeighbourIterator.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/NeighbourIterator.java @@ -41,7 +41,7 @@ public boolean hasNext() { @Override public ChipLocation next() { - return linksIter.next().destination; + return linksIter.next().destination(); } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Router.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Router.java index 8b5f711f89..daa23edf16 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Router.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Router.java @@ -19,7 +19,6 @@ import static java.util.Collections.unmodifiableCollection; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toUnmodifiableList; import static uk.ac.manchester.spinnaker.machine.MachineDefaults.ROUTER_AVAILABLE_ENTRIES; import java.util.Collection; @@ -185,10 +184,10 @@ public Router(HasChipLocation source, int nAvailableMulticastEntries, * has already been added. */ public void addLink(Link link) throws IllegalArgumentException { - if (links.containsKey(link.sourceLinkDirection)) { + if (links.containsKey(link.sourceLinkDirection())) { throw new IllegalArgumentException("Link already exists: " + link); } - links.put(link.sourceLinkDirection, link); + links.put(link.sourceLinkDirection(), link); } /** @@ -248,7 +247,7 @@ public int size() { * @return A Stream over the destination locations. */ public Stream streamNeighbouringChipsCoords() { - return links.values().stream().map(link -> link.destination); + return links.values().stream().map(Link::destination); } /** @@ -271,14 +270,13 @@ public MappableIterable iterNeighbouringChipsCoords() { * @return The destination locations */ public List neighbouringChipsCoords() { - return links.values().stream().map(link -> link.destination) - .collect(toUnmodifiableList()); + return links.values().stream().map(Link::destination).toList(); } @Override public String toString() { return links.entrySet().stream().map( - entry -> entry.getKey() + ":" + entry.getValue().destination) + entry -> entry.getKey() + ":" + entry.getValue().destination()) .collect(joining(" ", "Router[", "]")); } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/SpiNNakerTriadGeometry.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/SpiNNakerTriadGeometry.java index d33f00a2b3..4c609b0e44 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/SpiNNakerTriadGeometry.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/SpiNNakerTriadGeometry.java @@ -250,13 +250,13 @@ public Set getPotentialRootChips( var results = new LinkedHashSet(); int maxWidth; int maxHeight; - if (dimensions.width % triadWidth == 0 - && dimensions.height % triadHeight == 0) { - maxWidth = dimensions.width; - maxHeight = dimensions.height; + if (dimensions.width() % triadWidth == 0 + && dimensions.height() % triadHeight == 0) { + maxWidth = dimensions.width(); + maxHeight = dimensions.height(); } else { - maxWidth = dimensions.width - SIZE_X_OF_ONE_BOARD + 1; - maxHeight = dimensions.height - SIZE_Y_OF_ONE_BOARD + 1; + maxWidth = dimensions.width() - SIZE_X_OF_ONE_BOARD + 1; + maxHeight = dimensions.height() - SIZE_Y_OF_ONE_BOARD + 1; if (maxWidth < 0 || maxHeight < 0) { results.add(ZERO_ZERO); return results; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java index 0c24111b8e..2bcece41ab 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java @@ -117,9 +117,9 @@ public String toString() { public void addDefaults(MachineBean bean) { ChipResources defaults; if (details.getIpAddress() == null) { - defaults = bean.getStandardResources(); + defaults = bean.standardResources(); } else { - defaults = bean.getEthernetResources(); + defaults = bean.ethernetResources(); } if (resources == null) { resources = defaults; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java index b97988db29..1be68bfcb4 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java @@ -163,8 +163,8 @@ public ChipLocation getLinkDestination(Direction direction, HasChipLocation source, Machine machine) { if (links != null) { for (var bean : links) { - if (bean.sourceDirection == direction) { - return bean.destination; + if (bean.sourceDirection() == direction) { + return bean.destination(); } } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java index eca1e58edb..660c032d59 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java @@ -33,17 +33,14 @@ * of the JSON model, the chip coordinates of the source are implicit. * * @author Christian-B + * @param destination + * Where the link is going. + * @param sourceDirection + * What direction the link is going in. */ -@UsedInJavadocOnly({Chip.class, Link.class}) -public class LinkBean { - /** Where the link is going. */ - @Valid - public final ChipLocation destination; - - /** What direction the link is going in. */ - @NotNull - public final Direction sourceDirection; - +@UsedInJavadocOnly({ Chip.class, Link.class }) +public record LinkBean(@Valid ChipLocation destination, + @NotNull Direction sourceDirection) { /** * Create a link description. * @@ -62,7 +59,7 @@ public LinkBean( int destinationX, @JsonProperty(value = "destinationY", required = true) int destinationY) { - destination = new ChipLocation(destinationX, destinationY); - sourceDirection = Direction.byId(sourceLinkId); + this(new ChipLocation(destinationX, destinationY), + Direction.byId(sourceLinkId)); } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java index dd96c5e045..0d816647cd 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java @@ -16,7 +16,7 @@ */ package uk.ac.manchester.spinnaker.machine.bean; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; @@ -31,26 +31,25 @@ * Used to build a {@link Machine} from JSON. * * @author Christian-B + * @param dimensions + * The dimensions of the machine. + * @param root + * The root chip of the machine. + * @param ethernetResources + * The default resources of ethernet-enabled chips. + * @param standardResources + * The default resources of chips that are not ethernet-enabled. + * @param chips + * The chips. */ @UsedInJavadocOnly(Machine.class) -public class MachineBean { - @Valid - private final MachineDimensions dimensions; - - @Valid - private final ChipLocation root; - - @Valid - private final ChipResources ethernetResources; - - @Valid - private final ChipResources standardResources; - - private final List<@Valid ChipBean> chips; - +public record MachineBean(// + @Valid MachineDimensions dimensions, // + @Valid ChipLocation root, // + @Valid ChipResources ethernetResources, // + @Valid ChipResources standardResources, // + List<@Valid ChipBean> chips) { /** - * Main Constructor that sets all values. - * * @param height * The height of the Machine in Chips * @param width @@ -66,6 +65,7 @@ public class MachineBean { * @param chips * Beans for each Chips on the machine. */ + @JsonCreator public MachineBean( @JsonProperty(value = "height", required = true) int height, @JsonProperty(value = "width", required = true) int width, @@ -76,37 +76,8 @@ public MachineBean( ChipResources standardResources, @JsonProperty(value = "chips", required = true) List chips) { - dimensions = new MachineDimensions(width, height); - this.root = root; - this.chips = chips; - this.ethernetResources = ethernetResources; - this.standardResources = standardResources; - } - - /** @return The dimensions of the machine. */ - @JsonIgnore - public MachineDimensions getMachineDimensions() { - return dimensions; - } - - /** @return The root chip of the machine. */ - public ChipLocation getRoot() { - return root; - } - - /** @return the default resources of ethernet-enabled chips */ - public ChipResources getEthernetResources() { - return ethernetResources; - } - - /** @return the default resources of chips that are not ethernet-enabled */ - public ChipResources getStandardResources() { - return standardResources; - } - - /** @return the chips */ - public List getChips() { - return chips; + this(new MachineDimensions(width, height), root, ethernetResources, + standardResources, chips); } @Override diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestVirtualMachine.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestVirtualMachine.java index e9a869df20..98928a25b7 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestVirtualMachine.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestVirtualMachine.java @@ -60,7 +60,7 @@ public void testSmallBoards() { var bad = MachineDefaults.FOUR_CHIP_DOWN_LINKS .get(chip.asChipLocation()); for (var link : chip.router) { - assertThat(bad, not(hasItems(link.sourceLinkDirection))); + assertThat(bad, not(hasItems(link.sourceLinkDirection()))); } } } diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestMachineBean.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestMachineBean.java index 0135654d03..e54c7b0e76 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestMachineBean.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/bean/TestMachineBean.java @@ -57,8 +57,8 @@ public void testSevenEight() throws IOException { var fromJson = mapper.readValue(url, MachineBean.class); var machine = new Machine(fromJson); - assertEquals(24, machine.machineDimensions.height); - assertEquals(12, machine.machineDimensions.width); + assertEquals(24, machine.machineDimensions.height()); + assertEquals(12, machine.machineDimensions.width()); assertNotNull(machine); } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java index c52c5add02..991e1588a7 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java @@ -122,7 +122,7 @@ private static int getRecordingRegion(Connection conn, int coreID, // core_id, local_region_index, address s.setInt(FIRST, coreID); s.setInt(SECOND, region.regionIndex); - s.setInt(THIRD, region.startAddress.address); + s.setInt(THIRD, region.startAddress.address()); s.executeUpdate(); try (var keys = s.getGeneratedKeys()) { while (keys.next()) { diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index 718361a7b9..e4781757e2 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -208,7 +208,7 @@ private static void saveLoadingMetadata(Connection conn, CoreToLoadImpl core, MemoryLocation start, int memoryUsed, int memoryWritten) throws SQLException { try (var s = conn.prepareStatement(ADD_LOADING_METADATA)) { - s.setInt(FIRST, start.address); + s.setInt(FIRST, start.address()); s.setInt(SECOND, memoryUsed); s.setInt(THIRD, memoryWritten); s.setInt(FOURTH, core.id); From 73e15c5cbd79661b195200e3b62cca7c851ef969 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 1 Dec 2022 16:33:29 +0000 Subject: [PATCH 016/194] Sealed classes Can't use sealing as much as I'd like, but there's still quite a few places where I can use it. --- .../alloc/admin/AdminControllerImpl.java | 4 +- .../spinnaker/alloc/admin/AdminImpl.java | 2 +- .../alloc/admin/MachineDefinitionLoader.java | 105 ++++-------------- .../spinnaker/alloc/admin/UserControl.java | 3 +- .../alloc/allocator/AllocatorTask.java | 19 ++-- .../spinnaker/alloc/allocator/Epochs.java | 3 +- .../alloc/allocator/QuotaManager.java | 31 ++---- .../spinnaker/alloc/allocator/SpallocAPI.java | 6 +- .../spinnaker/alloc/bmp/BMPController.java | 9 +- .../spinnaker/alloc/bmp/FirmwareLoader.java | 3 +- .../spinnaker/alloc/db/DatabaseCache.java | 2 +- .../spinnaker/alloc/db/DatabaseEngine.java | 3 +- .../spinnaker/alloc/model/BoardRecord.java | 1 + .../alloc/security/LocalAuthProviderImpl.java | 48 ++++---- .../security/SimpleGrantedAuthority.java | 6 +- .../spinnaker/data_spec/MemoryRegion.java | 3 +- .../front_end/NoDropPacketContext.java | 2 +- .../download/BufferedReceivingData.java | 8 +- .../dse/SystemRouterTableContext.java | 2 +- .../spinnaker/front_end/iobuf/Replacer.java | 9 +- .../machine/MulticastRoutingEntry.java | 2 +- .../spinnaker/machine/RegionLocation.java | 53 ++------- .../spinnaker/machine/RoutingEntry.java | 2 +- .../machine/datalinks/AbstractDataLink.java | 1 + .../spinnaker/machine/tags/Tag.java | 3 +- .../spinnaker/machine/TestRegionLocation.java | 2 +- .../storage/threading/OTPrepared.java | 3 +- .../storage/threading/OTStatement.java | 3 +- .../storage/threading/OTWrapper.java | 3 +- 29 files changed, 123 insertions(+), 218 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java index c780d6c1b3..498370128f 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java @@ -595,8 +595,8 @@ public ModelAndView removeUserFromGroup(int id, int userid, public ModelAndView adjustGroupQuota(int id, int delta, RedirectAttributes attrs) { quotaManager.addQuota(id, delta * BOARD_HOUR).ifPresent(aq -> { - log.info("adjusted quota for group {} to {}", aq.getName(), - aq.getQuota()); + log.info("adjusted quota for group {} to {}", aq.name(), + aq.quota()); // addNotice(attrs, "quota updated"); }); return redirectTo(showGroupInfoUrl(id), attrs); diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java index 8cac00a302..3610729b7d 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminImpl.java @@ -75,7 +75,7 @@ public class AdminImpl implements AdminAPI { @Override public void importMachinesByContent( MachineDefinitionLoader.Configuration definitions) { - log.warn("CALLED importMachinesByContent({})", definitions.getMachines() + log.warn("CALLED importMachinesByContent({})", definitions.machines() .stream().map(Machine::getName).collect(toList())); loader.loadMachineDefinitions(definitions); } diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 4839ee26d2..441019cec8 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -419,88 +419,31 @@ public Machine build() { } /** - * A configuration description. JSON-deserializable (the only supported - * mechanism for generating an instance). Largely ignored as it represents - * configuration settings that we handle elsewhere. However, the + * A configuration description. JSON-deserializable (the only actually + * supported mechanism for generating an instance). Largely ignored as it + * represents configuration settings that we handle elsewhere. However, the * {@code machines} property is interesting. * * @author Donal Fellows + * @param machines + * The machines to manage. + * @param port + * The port for the service to listen on. (Ignored) + * @param ip + * The host address for the service to listen on. Empty = all + * interfaces. (Ignored) + * @param timeoutCheckInterval + * How often (in seconds) to check for timeouts. (Ignored) + * @param maxRetiredJobs + * How many retired jobs to retain. (Ignored) + * @param secondsBeforeFree + * Time to wait before freeing. (Ignored) */ - public static final class Configuration { - private @NotNull List<@Valid Machine> machines; - - @TCPPort - private int port; - - @IPAddress(nullOK = true, emptyOK = true) - private String ip; - - @Positive - private double timeoutCheckInterval; - - @Positive - private int maxRetiredJobs; - - @Positive - private int secondsBeforeFree; - - /** @return The machines to manage. */ - public List getMachines() { - return machines; - } - - void setMachines(List machines) { - this.machines = copy(machines); - } - - /** @return The port for the service to listen on. (Ignored) */ - public int getPort() { - return port; - } - - void setPort(int port) { - this.port = port; - } - - /** - * @return The host address for the service to listen on. Empty = all - * interfaces. (Ignored) - */ - public String getIp() { - return ip; - } - - void setIp(String ip) { - this.ip = ip; - } - - /** @return How often (in seconds) to check for timeouts. (Ignored) */ - public double getTimeoutCheckInterval() { - return timeoutCheckInterval; - } - - void setTimeoutCheckInterval(double timeoutCheckInterval) { - this.timeoutCheckInterval = timeoutCheckInterval; - } - - /** @return How many retired jobs to retain. (Ignored) */ - public int getMaxRetiredJobs() { - return maxRetiredJobs; - } - - void setMaxRetiredJobs(int maxRetiredJobs) { - this.maxRetiredJobs = maxRetiredJobs; - } - - /** @return Time to wait before freeing. (Ignored) */ - public int getSecondsBeforeFree() { - return secondsBeforeFree; - } - - void setSecondsBeforeFree(int secondsBeforeFree) { - this.secondsBeforeFree = secondsBeforeFree; - } - + public static record Configuration(// + @NotNull List<@Valid Machine> machines, @TCPPort int port, + @IPAddress(nullOK = true, emptyOK = true) String ip, + @Positive double timeoutCheckInterval, @Positive int maxRetiredJobs, + @Positive int secondsBeforeFree) { @Override public String toString() { return new StringBuilder("Configuration(").append("machines=") @@ -546,7 +489,7 @@ public List readMachineDefinitions(File file) throws IOException, JsonParseException, JsonMappingException { var cfg = mapper.readValue(file, Configuration.class); validate(cfg); - return cfg.getMachines(); + return cfg.machines(); } /** @@ -568,7 +511,7 @@ public List readMachineDefinitions(InputStream stream) throws IOException, JsonParseException, JsonMappingException { var cfg = mapper.readValue(stream, Configuration.class); validate(cfg); - return cfg.getMachines(); + return cfg.machines(); } /** @@ -659,7 +602,7 @@ public void loadMachineDefinitions(InputStream stream) */ public void loadMachineDefinitions(Configuration configuration) { try (var sql = new Updates()) { - for (var machine : configuration.getMachines()) { + for (var machine : configuration.machines()) { sql.transaction(() -> loadMachineDefinition(sql, machine)); } } diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java index 2031b2c905..debcd243c0 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java @@ -88,7 +88,8 @@ MappableIterable allUsers(boolean internal) { } @UsedInJavadocOnly(SQLQueries.class) - private class UserCheckSQL extends AbstractSQL { + private sealed class UserCheckSQL extends AbstractSQL + permits CreateSQL, DeleteUserSQL, UpdateAllSQL, UpdatePassSQL { private final Query userCheck = conn.query(GET_USER_ID); /** See {@link SQLQueries#GET_USER_DETAILS}. */ 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 a3a1e0bf2f..f06181ef25 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 @@ -158,7 +158,8 @@ public void allocate() { } /** 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; @@ -432,17 +433,13 @@ public void tombstone() { /** * Describes what the first stage of the tombstoner has copied. + * + * @param jobIds + * The IDs of jobs that were copied. + * @param allocIds + * The IDs of allocations that were copied. */ - static final class Copied { - private final List jobIds; - - private final List allocIds; - - private Copied(List jobIds, List allocIds) { - this.jobIds = jobIds; - this.allocIds = allocIds; - } - + static record Copied(List jobIds, List allocIds) { private Stream allocs() { return allocIds.stream().filter(Objects::nonNull); } 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 7faafcc79b..4b4f9bb884 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 @@ -125,7 +125,8 @@ private void waitUntil(long expiry) throws InterruptedException { * * @author Donal Fellows */ - public interface Epoch { + public sealed interface Epoch + permits BlacklistEpoch, JobsEpoch, MachinesEpoch { /** * Wait, for up to {@code timeout}, for a change. * 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 288ed4e87e..89b74688c5 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 @@ -65,7 +65,7 @@ public boolean mayCreateJob(int groupId) { } } - private class CreateCheckSQL extends AbstractSQL { + private final class CreateCheckSQL extends AbstractSQL { // TODO These should be combined (but one is an aggregate so...) private final Query getQuota = conn.query(GET_GROUP_QUOTA); @@ -119,7 +119,7 @@ public boolean shouldKillJob(int jobId) { return !mayLetJobContinue(jobId); } - private class ContinueCheckSQL extends AbstractSQL { + private final class ContinueCheckSQL extends AbstractSQL { private final Query getUsageAndQuota = conn.query(GET_JOB_USAGE_AND_QUOTA); @@ -160,29 +160,18 @@ 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 static 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")); } } - private class AdjustQuotaSQL extends AbstractSQL { + private final class AdjustQuotaSQL extends AbstractSQL { private final Query adjustQuota = conn.query(ADJUST_QUOTA); @Override @@ -223,7 +212,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); 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 c5e610b8a8..a32770bce8 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 @@ -234,7 +234,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. @@ -355,7 +356,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; 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 805f295856..da21f8b001 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 @@ -321,7 +321,8 @@ private interface ThrowingAction { void act() throws ProcessException, IOException, InterruptedException; } - private abstract class Request { + private abstract sealed class Request + permits BlacklistRequest, PowerRequest { final Machine machine; private int numTries = 0; @@ -1415,6 +1416,12 @@ void backgroundThread() { * No lock needed; this is the only thread that removes from * this queue. */ + + // TODO Change once pattern matching enabled by default + //switch (requests.poll()) { + //case PowerRequest pr -> processRequest(pr); + //case BlacklistRequest br -> processRequest(br); + //} var r = requests.poll(); if (r instanceof PowerRequest pr) { processRequest(pr); 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 a820319d49..b3b274ad02 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 @@ -221,8 +221,7 @@ private static class FlashDataSector { final ByteBuffer buf; FlashDataSector() { - buf = ByteBuffer.allocate(DATA_SECTOR_LENGTH); - buf.order(LITTLE_ENDIAN); + buf = ByteBuffer.allocate(DATA_SECTOR_LENGTH).order(LITTLE_ENDIAN); } static FlashDataSector registers(int numItems, List data) { diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java index be6a5bc90a..57ebc4f253 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseCache.java @@ -107,7 +107,7 @@ private Conn generateCachedDatabaseConnection() { * * @author Donal Fellows */ - private class CloserThread extends Thread { + private final class CloserThread extends Thread { private final Thread owner; private final Conn resource; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java index 8073bd4271..89d4a2b097 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java @@ -1135,7 +1135,8 @@ private String readSQL(Resource resource) { } } - private abstract static class StatementWrapper implements StatementCommon { + private abstract static sealed class StatementWrapper + implements StatementCommon permits QueryImpl, UpdateImpl { /** The statement being managed. */ final PreparedStatement s; 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 1695ea4899..b628c2b6bf 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 @@ -41,6 +41,7 @@ * @author Donal Fellows */ public class BoardRecord { + // This class is visible to JSTL expressions; it MUST be a bean // TODO convert to structured form private Integer id; 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 cd1e7794d5..76d89e0b1a 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 @@ -855,29 +855,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 static record LocalAuthResult(int userId, TrustLevel trustLevel, + String passInfo) { } /** @@ -910,12 +900,12 @@ 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); log.info("login success for {} at level {}", username, - details.trustLevel); + details.trustLevel()); return true; }); }, () -> false); @@ -975,16 +965,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"); }); 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 01cf7aa641..27229c88d9 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 @@ -20,11 +20,15 @@ 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 { private static final long serialVersionUID = 7765648523730760900L; private final String role; diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegion.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegion.java index b6a9193ba3..e1c3a19736 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegion.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/MemoryRegion.java @@ -26,7 +26,8 @@ * address in memory where they start (which is only chosen late in the region * creation process) and an index in the process's table of regions. */ -public abstract class MemoryRegion { +public abstract sealed class MemoryRegion + permits MemoryRegionReal, MemoryRegionReference { /** The base address of the region. Set after the fact. */ private MemoryLocation baseAddress = NULL; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/NoDropPacketContext.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/NoDropPacketContext.java index d52e98e54d..6d8827758c 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/NoDropPacketContext.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/NoDropPacketContext.java @@ -46,7 +46,7 @@ * @author Donal Fellows * @author Alan Stokes */ -public class NoDropPacketContext implements AutoCloseable { +public final class NoDropPacketContext implements AutoCloseable { private static final Logger log = getLogger(NoDropPacketContext.class); private ReinjectionStatus lastStatus; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/BufferedReceivingData.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/BufferedReceivingData.java index 12b5ec21ef..3c91b4ffee 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/BufferedReceivingData.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/BufferedReceivingData.java @@ -122,11 +122,11 @@ public RecordingRegion getRecordingRegion(RegionLocation location) { throw new IllegalArgumentException( "no regions known for " + coreLocation); } - if (value.size() < location.region || location.region < 0) { + if (value.size() < location.region() || location.region() < 0) { throw new IllegalArgumentException( "no region known for " + location); } - return value.get(location.region); + return value.get(location.region()); } /** @@ -144,11 +144,11 @@ public void storeDataInRegionBuffer(RegionLocation location, ByteBuffer data) throws StorageException { if (log.isInfoEnabled()) { log.info("retrieved {} bytes from region {} of {}", - data.remaining(), location.region, + data.remaining(), location.region(), location.asCoreLocation()); } storage.appendRecordingContents( - new Region(location, location.region, NULL, 0), data); + new Region(location, location.region(), NULL, 0), data); } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/SystemRouterTableContext.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/SystemRouterTableContext.java index c44274e9c1..a11af7dacd 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/SystemRouterTableContext.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/SystemRouterTableContext.java @@ -37,7 +37,7 @@ * * @author Donal Fellows */ -public class SystemRouterTableContext implements AutoCloseable { +public final class SystemRouterTableContext implements AutoCloseable { private static final Logger log = getLogger(SystemRouterTableContext.class); private final CoreSubsets monitorCores; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java index 744f994169..a6918cfdbf 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java @@ -150,14 +150,9 @@ private void applyReplacements(StringBuilder buffer, String[] parts) { } } - private static final class Replacement { - private final String match; - - private final int index; - + private static record Replacement(String match, int index) { private Replacement(MatchResult m, int index) { - match = m.group(); - this.index = index; + this(m.group(), index); } void replace(StringBuilder buffer, String[] parts) { diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MulticastRoutingEntry.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MulticastRoutingEntry.java index 20e8af8e19..f8b20bca19 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MulticastRoutingEntry.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MulticastRoutingEntry.java @@ -20,7 +20,7 @@ /** A multicast packet routing table entry. */ @Immutable -public class MulticastRoutingEntry extends RoutingEntry { +public final class MulticastRoutingEntry extends RoutingEntry { private final int key; private final int mask; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java index c82544c5c1..a2a8326bd5 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RegionLocation.java @@ -17,9 +17,6 @@ package uk.ac.manchester.spinnaker.machine; import static java.util.Comparator.comparing; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.COORD_SHIFT; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.CORE_SHIFT; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.REGION_SHIFT; import java.util.Comparator; @@ -29,28 +26,19 @@ * Holding case for a CoreLocation (X, Y and P) and the recording region ID. * * @author Christian + * @param x + * The Chip / Core's X value. + * @param y + * The Chip / Core's Y value. + * @param p + * The Core's P value. + * @param region + * The recording Region. */ @Immutable -public final class RegionLocation +public record RegionLocation(// + @ValidX int x, @ValidY int y, @ValidP int p, int region) implements HasCoreLocation, Comparable { - /** The Chip / Core's X value. */ - @ValidX - public final int x; - - /** The Chip / Core's Y value. */ - @ValidY - public final int y; - - /** The Core's P value. */ - @ValidP - public final int p; - - /** The recording Region. */ - public final int region; - - /** Precalculated hashcode. */ - private final int hashcode; - /** * Creates the Region based on a Core and a region. * @@ -60,12 +48,7 @@ public final class RegionLocation * The Region to use. */ public RegionLocation(HasCoreLocation core, int region) { - x = core.getX(); - y = core.getY(); - p = core.getP(); - this.region = region; - hashcode = ((((x << COORD_SHIFT) ^ y) << CORE_SHIFT) - ^ p) << REGION_SHIFT ^ region; + this(core.getX(), core.getY(), core.getP(), region); } @Override @@ -95,22 +78,8 @@ public int compareTo(RegionLocation o) { return COMPARATOR.compare(this, o); } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - return (obj instanceof RegionLocation that) && (x == that.x) - && (y == that.y) && (p == that.p) && (region == that.region); - } - @Override public String toString() { return "X:" + x + " Y:" + y + " P:" + p + "R: " + region; } - - @Override - public int hashCode() { - return hashcode; - } } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java index 5496227545..3c7c59a5bb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java @@ -33,7 +33,7 @@ /** A basic SpiNNaker routing entry. */ @Immutable @SuppressWarnings("Immutable") // Error Prone can't figure out this is true -public class RoutingEntry { +public sealed class RoutingEntry permits MulticastRoutingEntry { private final Set<@ValidP @NotNull Integer> processorIDs; private final Set linkIDs; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java index 8ed0362c5f..edbc466efb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java @@ -33,6 +33,7 @@ * @author Christian-B */ @Immutable +// Should be sealed, but tests interfere public abstract class AbstractDataLink implements HasChipLocation { /** IP address of the Datalink on the board. */ public final InetAddress boardAddress; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java index 336d7904a4..fd3525b64e 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java @@ -26,7 +26,8 @@ import uk.ac.manchester.spinnaker.utils.validation.UDPPort; /** Common properties of SpiNNaker IP tags and reverse IP tags. */ -public abstract class Tag implements Comparable { +public abstract sealed class Tag + implements Comparable permits IPTag, ReverseIPTag { /** The board address associated with this tagID. */ @NotNull private final InetAddress boardAddress; diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestRegionLocation.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestRegionLocation.java index b1eeadf3d4..9b968654d5 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestRegionLocation.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/TestRegionLocation.java @@ -32,7 +32,7 @@ public void testBasicUse() { assertEquals(2, r1.getX()); assertEquals(4, r1.getY()); assertEquals(6, r1.getP()); - assertEquals(8, r1.region); + assertEquals(8, r1.region()); assertEquals(r1, r1); assertNotEquals(r1, "r1"); diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTPrepared.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTPrepared.java index abf77e73e3..01207ad8e3 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTPrepared.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTPrepared.java @@ -42,7 +42,8 @@ * * @author Donal Fellows */ -class OTPrepared extends OTStatement implements PreparedStatement { +sealed class OTPrepared extends OTStatement + implements PreparedStatement permits OTCallable { private final PreparedStatement s; OTPrepared(OneThread ot, PreparedStatement s) { diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTStatement.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTStatement.java index 0dd586c7d6..8d8aca5642 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTStatement.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTStatement.java @@ -27,7 +27,8 @@ * * @author Donal Fellows */ -class OTStatement extends OTWrapper implements Statement { +sealed class OTStatement extends OTWrapper + implements Statement permits OTPrepared { private final Statement s; OTStatement(OneThread ot, Statement s) { diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTWrapper.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTWrapper.java index 3133a99216..869b08b94f 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTWrapper.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/threading/OTWrapper.java @@ -33,7 +33,8 @@ * * @author Donal Fellows */ -abstract class OTWrapper implements Wrapper { +abstract sealed class OTWrapper implements + Wrapper permits OTConnection, OTMeta, OTResults, OTRSMeta, OTStatement { private final OneThread ot; private final Wrapper w; From a37f037eb3405da2bc488b5836ce546461cfac8b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 12:44:12 +0000 Subject: [PATCH 017/194] checkstyle has opinions about records --- .../alloc/admin/MachineDefinitionLoader.java | 2 +- .../spinnaker/alloc/admin/UserControl.java | 2 +- .../spinnaker/alloc/allocator/AllocatorTask.java | 12 ++++++++---- .../spinnaker/alloc/allocator/QuotaManager.java | 2 +- .../spinnaker/alloc/bmp/TransceiverFactory.java | 2 +- .../spinnaker/alloc/model/DownLink.java | 3 +-- .../alloc/security/LocalAuthProviderImpl.java | 6 ++++-- .../security/MyAuthenticationFailureHandler.java | 2 +- .../spinnaker/alloc/web/CreateJobRequest.java | 7 +++---- .../spinnaker/alloc/web/IssueReportRequest.java | 2 +- .../spinnaker/alloc/web/MachinesResponse.java | 4 ++-- .../spalloc/messages/BoardCoordinates.java | 2 +- .../spinnaker/spalloc/messages/Connection.java | 2 +- .../spinnaker/spalloc/messages/WhereIs.java | 6 +++--- .../spinnaker/transceiver/GetHeapProcess.java | 4 ++-- .../spinnaker/transceiver/Transceiver.java | 4 ++-- .../front_end/download/DataGatherer.java | 3 +-- .../front_end/download/request/Vertex.java | 2 +- .../spinnaker/front_end/dse/ExecutionContext.java | 5 ++--- .../spinnaker/front_end/iobuf/Replacer.java | 2 +- .../uk/ac/manchester/spinnaker/machine/Link.java | 15 ++++++++++----- .../spinnaker/machine/board/BMPBoard.java | 2 +- .../spinnaker/machine/board/BMPCoords.java | 2 +- .../spinnaker/machine/board/PhysicalCoords.java | 2 +- .../spinnaker/machine/board/TriadCoords.java | 2 +- .../spinnaker/machine/datalinks/InetIdTuple.java | 2 +- 26 files changed, 53 insertions(+), 46 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 441019cec8..d072ed167a 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -439,7 +439,7 @@ public Machine build() { * @param secondsBeforeFree * Time to wait before freeing. (Ignored) */ - public static record Configuration(// + public record Configuration(// @NotNull List<@Valid Machine> machines, @TCPPort int port, @IPAddress(nullOK = true, emptyOK = true) String ip, @Positive double timeoutCheckInterval, @Positive int maxRetiredJobs, diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java index debcd243c0..f2ef4ca2a3 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java @@ -605,7 +605,7 @@ public PasswordChangeRecord updateUser(Principal principal, * @see UserControl#updateUser(Principal, PasswordChangeRecord, * UpdatePassSQL) */ - private static record GetUserResult(PasswordChangeRecord baseUser, + private record GetUserResult(PasswordChangeRecord baseUser, String oldEncPass) { private GetUserResult(Row row) { this(passChange(row), row.getString("encrypted_password")); 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 f06181ef25..8bda25a1ef 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 @@ -114,10 +114,14 @@ public class AllocatorTask extends DatabaseAwareBean * 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 record Rectangle(int width, int height, - /** Depth of rectangle. 1 or 3 */ - int 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); @@ -439,7 +443,7 @@ public void tombstone() { * @param allocIds * The IDs of allocations that were copied. */ - static record Copied(List jobIds, List allocIds) { + record Copied(List jobIds, List allocIds) { private Stream allocs() { return allocIds.stream().filter(Objects::nonNull); } 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 89b74688c5..67c1dd469f 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 @@ -165,7 +165,7 @@ public Optional addQuota(int groupId, int delta) { * @param quota * The new quota of the group. */ - public static record AdjustedQuota(String name, Long quota) { + public record AdjustedQuota(String name, Long quota) { private AdjustedQuota(Row row) { this(row.getString("group_name"), row.getLong("quota")); } 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 21afdd1d0f..12879e4bfb 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 @@ -68,7 +68,7 @@ public class TransceiverFactory implements TransceiverFactoryAPI { private static final Logger log = getLogger(TransceiverFactory.class); - private static record Key(String machine, BMPCoords bmp) { + private record Key(String machine, BMPCoords bmp) { } @GuardedBy("itself") 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 2f066555b5..f9a5669206 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 @@ -46,8 +46,7 @@ public record DownLink(@Valid DownLink.End end1, @Valid DownLink.End end2) { * In which direction does this end of the link go? */ @Immutable - public static record End(@Valid BoardCoords board, - @NotNull Direction direction) { + public record End(@Valid BoardCoords board, @NotNull Direction direction) { } /** 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 76d89e0b1a..a37e141043 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 @@ -98,6 +98,7 @@ * @see AuthProperties Configuration properties * @author Donal Fellows */ +@SuppressWarnings("deprecation") @Service public class LocalAuthProviderImpl extends DatabaseAwareBean implements LocalAuthenticationProvider { @@ -295,6 +296,7 @@ public Authentication updateAuthentication(SecurityContext ctx) { /** The classes that we know we don't ever want to handle. */ private static final Class[] UNSUPPORTED_AUTH_TOKEN_CLASSES = { AnonymousAuthenticationToken.class, RememberMeAuthenticationToken.class, + // TODO do we replace RunAsUserToken.class? RunAsUserToken.class, TestingAuthenticationToken.class }; @@ -419,7 +421,7 @@ private Authentication authorizeOpenId(String name, String subject, } /** Holds either a {@link OAuth2User} or a {@link Jwt}. */ - private static record OriginatingCredential(OAuth2User user, + private record OriginatingCredential(OAuth2User user, OAuth2AccessToken token) { OriginatingCredential(OAuth2User user) { this(requireNonNull(user), null); @@ -866,7 +868,7 @@ public void mapAuthorities(OidcUserAuthority user, * The encoded password. */ @Immutable - private static record LocalAuthResult(int userId, TrustLevel trustLevel, + private record LocalAuthResult(int userId, TrustLevel trustLevel, String passInfo) { } 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 ff5e446ed0..c90b732ff2 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 @@ -68,6 +68,6 @@ public void onAuthenticationFailure(HttpServletRequest request, new AuthFailureObject(message, now())); } - static record AuthFailureObject(String message, Instant timestamp) { + record AuthFailureObject(String message, Instant timestamp) { } } 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 ee68d5c60c..d8fc35c120 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 @@ -165,7 +165,7 @@ private boolean isKeepaliveIntervalInRange() { * @param height * The height of the rectangle of boards to allocate, in triads. */ - public static record Dimensions(@ValidTriadWidth int width, + public record Dimensions(@ValidTriadWidth int width, @ValidTriadHeight int height) { } @@ -187,9 +187,8 @@ public static record Dimensions(@ValidTriadWidth int width, * @param address * The IP address of the board. */ - public static record SpecificBoard(@ValidTriadX Integer x, - @ValidTriadY Integer y, @ValidTriadZ Integer z, - @ValidCabinetNumber Integer cabinet, + 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) { 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 f5abb12bec..cd45023841 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 @@ -68,7 +68,7 @@ public record IssueReportRequest( * @param address * The IP address of the board. */ - public static record ReportedBoard(@Valid ChipLocation chip, + public record ReportedBoard(@Valid ChipLocation chip, @ValidTriadX Integer x, @ValidTriadY Integer y, @ValidTriadZ Integer z, @ValidCabinetNumber Integer cabinet, @ValidFrameNumber Integer frame, @ValidBoardNumber Integer board, 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 007796cf92..acba2ca28e 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 @@ -37,7 +37,7 @@ * @param machines * The list of machines known to the service. */ -public final record MachinesResponse(List machines) { +public record MachinesResponse(List machines) { /** * A brief, summary description of a machine. * @@ -57,7 +57,7 @@ public final record MachinesResponse(List machines) { * @param deadLinks * The dead links on the machine. */ - public static record BriefMachineDescription(String name, List tags, + public record BriefMachineDescription(String name, List tags, URI uri, int width, int height, List deadBoards, List deadLinks) { } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java index f9201d3f51..59c163ebf3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardCoordinates.java @@ -45,7 +45,7 @@ @JsonFormat(shape = ARRAY) @JsonAutoDetect(setterVisibility = NON_PRIVATE) @Immutable -public final record BoardCoordinates( +public record BoardCoordinates( @JsonProperty(value = "x", defaultValue = "0") @ValidTriadX int x, @JsonProperty(value = "y", defaultValue = "0") @ValidTriadY int y, @JsonProperty(value = "z", defaultValue = "0") @ValidTriadZ int z) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java index c5ad3cefd3..52e7211ea9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java @@ -44,7 +44,7 @@ @JsonFormat(shape = ARRAY) @JsonDeserialize(builder = Connection.Builder.class) @Immutable -public final record Connection(@Valid ChipLocation chip, +public record Connection(@Valid ChipLocation chip, @IPAddress String hostname) { /** * Create. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java index 2c1b6099b6..6427787371 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIs.java @@ -42,9 +42,9 @@ */ @Immutable @JsonDeserialize(builder = WhereIs.Builder.class) -public final record WhereIs(ChipLocation jobChip, Integer jobId, - ChipLocation chip, BoardCoordinates logical, String machine, - ChipLocation boardChip, BoardPhysicalCoordinates physical) { +public record WhereIs(ChipLocation jobChip, Integer jobId, ChipLocation chip, + BoardCoordinates logical, String machine, ChipLocation boardChip, + BoardPhysicalCoordinates physical) { @Override public String toString() { return "jobChip: " + jobChip + " jobId: " + jobId + " chip: " + chip diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java index 761f249069..e22ac862bc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetHeapProcess.java @@ -221,7 +221,7 @@ private IntBuffer readFromAddress(HasChipLocation chip, } @SARKStruct("heap_t") - private static record HeapHeader(// + private record HeapHeader(// @SARKField("free") MemoryLocation free, @SARKField("first") MemoryLocation first, @SARKField("last") MemoryLocation last, @@ -237,7 +237,7 @@ private static record HeapHeader(// } @SARKStruct("block_t") - private static record BlockHeader(// + private record BlockHeader(// @SARKField("next") MemoryLocation next, @SARKField("free") MemoryLocation free) { BlockHeader(IntBuffer data) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index be7f1560b6..5319a18a5b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -2589,8 +2589,8 @@ ConnectionSelector> getBMPConnection() { * @param chip * What chip to talk to. */ - public static final record ConnectionDescriptor(InetAddress hostname, - Integer portNumber, ChipLocation chip) { + public record ConnectionDescriptor(InetAddress hostname, Integer portNumber, + ChipLocation chip) { /** * Create a connection descriptor. * diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java index bb2da832e5..ee503320c9 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java @@ -238,8 +238,7 @@ private int countPlacements(List gatherers) { * The outer list could theoretically be done in any order... but * needs to be processed single-threaded anyway. */ - private static record WorkItems(Monitor monitor, - List> regions) { + private record WorkItems(Monitor monitor, List> regions) { } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java index 9445a2d3d2..491161273a 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java @@ -46,7 +46,7 @@ * buffering. */ @JsonFormat(shape = OBJECT) -public final record Vertex(String label, @NotNull MemoryLocation base, +public record Vertex(String label, @NotNull MemoryLocation base, @NotNull int[] recordedRegionIds) { /** * Create a minimal vertex, possibly using an unmarshaller. diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java index 283e1b30b0..64962c02ec 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecutionContext.java @@ -204,11 +204,10 @@ static class DanglingReferenceException } @Immutable - private static record RegionToRef(CoreLocation core, - MemoryLocation pointer) { + private record RegionToRef(CoreLocation core, MemoryLocation pointer) { } - private static record CoreToFill(Executor executor, MemoryLocation start, + private record CoreToFill(Executor executor, MemoryLocation start, CoreLocation core, List refs) { CoreToFill(Executor executor, MemoryLocation start, CoreLocation core) { this(executor, start, core, new ArrayList<>()); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java index a6918cfdbf..9e01beb327 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java @@ -150,7 +150,7 @@ private void applyReplacements(StringBuilder buffer, String[] parts) { } } - private static record Replacement(String match, int index) { + private record Replacement(String match, int index) { private Replacement(MatchResult m, int index) { this(m.group(), index); } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java index f6620b0190..f6ce551bed 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java @@ -17,6 +17,7 @@ package uk.ac.manchester.spinnaker.machine; import javax.validation.Valid; +import javax.validation.constraints.NotNull; import com.google.errorprone.annotations.Immutable; @@ -27,13 +28,17 @@ * "https://github.com/SpiNNakerManchester/SpiNNMachine/blob/master/spinn_machine/link.py"> * Python Version * @author Christian-B - * @param source The coordinates of the source chip of the link. - * @param sourceLinkDirection The direction of the link in the source chip. - * @param destination The coordinate of the destination chip of the link. + * @param source + * The coordinates of the source chip of the link. + * @param sourceLinkDirection + * The direction of the link in the source chip. + * @param destination + * The coordinate of the destination chip of the link. */ @Immutable -public final record Link(@Valid ChipLocation source, - Direction sourceLinkDirection, @Valid ChipLocation destination) { +public record Link(@Valid ChipLocation source, + @NotNull Direction sourceLinkDirection, + @Valid ChipLocation destination) { // Note: multicast_default_from and multicast_default_to not implemented /** * @param source diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java index ff9b0bd5e9..e2688e15cb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPBoard.java @@ -23,7 +23,7 @@ * @param board * The board number. */ -public final record BMPBoard(@ValidBoardNumber int board) { +public record BMPBoard(@ValidBoardNumber int board) { /** * The maximum board number. There can be only up to 24 boards per frame. */ diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 9be28a1691..063c204b2c 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -57,7 +57,7 @@ */ @Immutable @JsonDeserialize(using = BMPCoords.Deserializer.class) -public final record BMPCoords(@ValidCabinetNumber int cabinet, +public record BMPCoords(@ValidCabinetNumber int cabinet, @ValidFrameNumber int frame) implements Comparable { /** Parses the result of {@link #toString()}. */ private static final Pattern PATTERN = diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index 20a63f8989..b9ed6a0395 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -58,7 +58,7 @@ */ @Immutable @JsonDeserialize(using = PhysicalCoords.Deserializer.class) -public final record PhysicalCoords(// +public record PhysicalCoords(// @JsonProperty("c") @ValidCabinetNumber int c, @JsonProperty("f") @ValidFrameNumber int f, @JsonProperty("b") @ValidBoardNumber int b) diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index 1d9a5f9635..7f7ae15379 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -58,7 +58,7 @@ * Z coordinate of triad. */ @JsonDeserialize(using = TriadCoords.Deserializer.class) -public final record TriadCoords(// +public record TriadCoords(// @JsonProperty("x") @ValidTriadX int x, @JsonProperty("y") @ValidTriadY int y, @JsonProperty("z") @ValidTriadZ int z) diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java index 3bba906821..2d0078835c 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/InetIdTuple.java @@ -30,5 +30,5 @@ * The ID of this tuple. */ @Immutable -public final record InetIdTuple(InetAddress address, int id) { +public record InetIdTuple(InetAddress address, int id) { } From 8e169b17a94064c996cf7988fe4201d9db136ae8 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 13:04:23 +0000 Subject: [PATCH 018/194] Inline the smaller "large" queries --- .../alloc/allocator/AllocatorTask.java | 6 +- .../spinnaker/alloc/allocator/Spalloc.java | 2 +- .../spinnaker/alloc/db/SQLQueries.java | 170 +++++++++++------- .../main/resources/queries/find_location.sql | 21 --- .../queries/get_allocation_tasks.sql | 35 ---- .../resources/queries/get_reported_boards.sql | 30 ---- .../queries/issue_change_for_job.sql | 21 --- .../spinnaker/alloc/db/DMLTest.java | 2 +- .../spinnaker/alloc/db/DQLTest.java | 6 +- 9 files changed, 116 insertions(+), 177 deletions(-) delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/find_location.sql delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/issue_change_for_job.sql 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 8bda25a1ef..c9aa1d4170 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 @@ -189,7 +189,7 @@ private sealed 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); } @@ -263,13 +263,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); 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 cc79402039..4d4845d5ba 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 @@ -987,7 +987,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); 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 9c79c4495f..9fc29013b3 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 @@ -2414,6 +2414,114 @@ INSERT INTO blacklist_ops( 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 = """ + SELECT + board_reports.board_id, + COUNT(*) AS num_reports, + boards.x, + boards.y, + boards.z, + boards.address + FROM + board_reports + JOIN boards USING (board_id) + JOIN jobs USING (job_id) + WHERE functioning IS NOT 0 + GROUP BY board_reports.board_id + HAVING 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) + """; + // SQL loaded from files because it is too complicated otherwise! /** @@ -2456,37 +2564,6 @@ INSERT INTO blacklist_ops( @Value("classpath:queries/find_rectangle_at.sql") protected Resource findRectangleAt; - /** - * 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 - @Value("classpath:queries/find_location.sql") - protected Resource findLocation; - - /** 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 - @Value("classpath:queries/issue_change_for_job.sql") - protected Resource issueChangeForJob; - /** * 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 @@ -2713,37 +2790,6 @@ INSERT INTO blacklist_ops( @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; - /** * 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 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 9cefc4516a..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/find_location.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - -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/get_allocation_tasks.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql deleted file mode 100644 index b1eb007875..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/get_allocation_tasks.sql +++ /dev/null @@ -1,35 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - --- 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_reported_boards.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql deleted file mode 100644 index b498275a17..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/get_reported_boards.sql +++ /dev/null @@ -1,30 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - --- Get boards with more problem reports than a critical threshold -SELECT - board_reports.board_id, - COUNT(*) AS num_reports, - boards.x, - boards.y, - boards.z, - boards.address -FROM - board_reports - JOIN boards USING (board_id) - JOIN jobs USING (job_id) -WHERE functioning IS NOT 0 -GROUP BY board_reports.board_id -HAVING 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 f6ed464db4..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/issue_change_for_job.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - -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/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 9381ca8f2e..6ef72a78ec 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 @@ -252,7 +252,7 @@ void setInProgress() { @Test void issueChangeForJob() { assumeWritable(c); - try (var u = c.update(issueChangeForJob)) { + try (var u = c.update(ISSUE_CHANGE_FOR_JOB)) { assertEquals(11, u.getNumArguments()); c.transaction(() -> { // No such job 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 92e856441d..4906e02454 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 @@ -427,7 +427,7 @@ void getRootCoords() { @Test void getAllocationTasks() { - try (var q = c.query(getAllocationTasks)) { + try (var q = c.query(GET_ALLOCATION_TASKS)) { assertEquals(1, q.getNumArguments()); assertEquals(Set.of("req_id", "job_id", "num_boards", "width", "height", "board_id", "machine_id", "max_dead_boards", @@ -534,7 +534,7 @@ void findRectangleAt() { @Test void findLocation() { - try (var q = c.query(findLocation)) { + try (var q = c.query(FIND_LOCATION)) { assertEquals(2, q.getNumArguments()); assertEquals(Set.of("x", "y", "z"), q.getRowColumnNames()); c.transaction(() -> { @@ -1050,7 +1050,7 @@ void getLocalUserDetails() { @Test void getReportedBoards() { - try (var q = c.query(getReportedBoards)) { + try (var q = c.query(GET_REPORTED_BOARDS)) { assertEquals(1, q.getNumArguments()); assertEquals( Set.of("board_id", "num_reports", "x", "y", "z", "address"), From fd6d318e834df10b762a8771d3e4131b4081bbb1 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 13:06:26 +0000 Subject: [PATCH 019/194] Exception has changed --- .../uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java index f7eb0e8aad..a0dbb945a3 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java @@ -53,7 +53,7 @@ public void testSlice() { assertEquals(0x01020304, r.getInt()); // Check range sanity enforced - assertThrows(IllegalArgumentException.class, + assertThrows(IndexOutOfBoundsException.class, () -> ByteBufferUtils.slice(r, 0, 16)); } } From 4c17da257f4d50142b4190b33d8e631ea2a5e428 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 15:30:49 +0000 Subject: [PATCH 020/194] Inline some more "large" queries, and add doc comments to rest --- .../alloc/allocator/AllocatorTask.java | 4 +- .../spinnaker/alloc/allocator/Spalloc.java | 2 +- .../spinnaker/alloc/db/SQLQueries.java | 162 ++++++++++++------ .../queries/allocation_connected.sql | 5 + .../queries/connected_boards_at_coords.sql | 5 + .../copy-allocs-to-historical-data.sql | 27 --- .../queries/copy-jobs-to-historical-data.sql | 42 ----- .../queries/find_board_by_global_chip.sql | 4 + .../queries/find_board_by_ip_address.sql | 4 + .../queries/find_board_by_job_chip.sql | 4 + .../queries/find_board_by_logical_coords.sql | 4 + .../queries/find_board_by_physical_coords.sql | 4 + .../main/resources/queries/find_rectangle.sql | 2 + .../resources/queries/find_rectangle_at.sql | 2 + .../main/resources/queries/get_dead_links.sql | 44 ----- .../queries/get_jobs_with_changes.sql | 6 + .../src/main/resources/queries/perimeter.sql | 21 ++- .../spinnaker/alloc/db/DMLTest.java | 4 +- .../spinnaker/alloc/db/DQLTest.java | 2 +- 19 files changed, 174 insertions(+), 174 deletions(-) delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/copy-allocs-to-historical-data.sql delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/copy-jobs-to-historical-data.sql delete mode 100644 SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql 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 c9aa1d4170..1659c75ea0 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 @@ -480,8 +480,8 @@ int numAllocs() { * @return Description of the tombstoned IDs */ private Copied tombstone(Connection conn) { - try (var copyJobs = conn.query(copyJobsToHistoricalData); - var copyAllocs = conn.query(copyAllocsToHistoricalData); + try (var copyJobs = conn.query(COPY_JOBS_TO_HISTORICAL_DATA); + var copyAllocs = conn.query(COPY_ALLOCS_TO_HISTORICAL_DATA); var deleteJobs = conn.update(DELETE_JOB_RECORD); var deleteAllocs = conn.update(DELETE_ALLOC_RECORD)) { var grace = historyProps.getGracePeriod(); 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 4d4845d5ba..7116499e6c 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 @@ -848,7 +848,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(id).map(Spalloc::makeDownLinkFromRow).toList()); synchronized (Spalloc.this) { 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 9fc29013b3..bbd9e46d15 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 @@ -2522,6 +2522,113 @@ INSERT INTO pending_changes( :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 + """; + // SQL loaded from files because it is too complicated otherwise! /** @@ -2743,8 +2850,10 @@ INSERT INTO pending_changes( 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") @@ -2753,8 +2862,8 @@ INSERT INTO pending_changes( /** * 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 */ @@ -2768,49 +2877,4 @@ INSERT INTO pending_changes( @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; - - /** - * 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") - @Value("classpath:queries/copy-jobs-to-historical-data.sql") - protected Resource copyJobsToHistoricalData; - - /** - * 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") - @Value("classpath:queries/copy-allocs-to-historical-data.sql") - protected Resource copyAllocsToHistoricalData; } diff --git a/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql b/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql index 510b5c6268..db4210b5b5 100644 --- a/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql +++ b/SpiNNaker-allocserv/src/main/resources/queries/allocation_connected.sql @@ -13,6 +13,11 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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 ( VALUES (: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 4b2231d567..ccf3c6891a 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 @@ -13,6 +13,11 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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 ( VALUES (:machine_id, :x, :y, :z, :width, :height, :depth)), diff --git a/SpiNNaker-allocserv/src/main/resources/queries/copy-allocs-to-historical-data.sql b/SpiNNaker-allocserv/src/main/resources/queries/copy-allocs-to-historical-data.sql deleted file mode 100644 index 75daf02f4e..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/copy-allocs-to-historical-data.sql +++ /dev/null @@ -1,27 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - -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; diff --git a/SpiNNaker-allocserv/src/main/resources/queries/copy-jobs-to-historical-data.sql b/SpiNNaker-allocserv/src/main/resources/queries/copy-jobs-to-historical-data.sql deleted file mode 100644 index 115ac8ba56..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/copy-jobs-to-historical-data.sql +++ /dev/null @@ -1,42 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - -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; 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 6599af42a2..d1bc7420e3 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 @@ -13,6 +13,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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 c7e3096c56..99f8465131 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 @@ -13,6 +13,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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 2cdb1d7347..5814b86604 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 @@ -13,6 +13,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- Locate a board (using a full set of coordinates) based on allocation-local +-- chip coordinates. + WITH args(job, root, x, y) AS (VALUES (: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 f8104720ba..83279eea43 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 @@ -13,6 +13,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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 a20fd55afd..56edfe7870 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 @@ -13,6 +13,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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_rectangle.sql b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql index 4a64e1ffa1..ad3f3b423c 100644 --- a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql +++ b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle.sql @@ -13,6 +13,8 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- + WITH -- 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 b27d83c0c8..c6da4514c2 100644 --- a/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql +++ b/SpiNNaker-allocserv/src/main/resources/queries/find_rectangle_at.sql @@ -13,6 +13,8 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- + WITH -- 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_dead_links.sql b/SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql deleted file mode 100644 index d4e334001c..0000000000 --- a/SpiNNaker-allocserv/src/main/resources/queries/get_dead_links.sql +++ /dev/null @@ -1,44 +0,0 @@ --- Copyright (c) 2021 The University of Manchester --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - --- 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 4f8ac42090..e21cfa1b6c 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 @@ -13,6 +13,12 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +-- -------------------------------------------------------------------------- +-- 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/perimeter.sql b/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql index b783c0d365..cbbb524a4d 100644 --- a/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql +++ b/SpiNNaker-allocserv/src/main/resources/queries/perimeter.sql @@ -13,13 +13,22 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -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 boards.* FROM boards WHERE boards.allocated_job = :job_id) + SELECT boards.board_id FROM boards WHERE boards.allocated_job = :job_id) SELECT links.board_1 AS board_id, links.dir_1 AS direction - FROM links JOIN bs ON links.board_1 IN (SELECT board_id FROM bs) - WHERE links.live AND NOT links.board_2 IN (SELECT board_id FROM bs) + FROM links + JOIN bs ON links.board_1 IN (SELECT board_id FROM bs) + WHERE links.live + AND NOT links.board_2 IN (SELECT board_id FROM bs) UNION SELECT links.board_2 AS board_id, links.dir_2 AS direction - FROM links JOIN bs ON links.board_2 IN (SELECT board_id FROM bs) - WHERE links.live AND NOT links.board_1 IN (SELECT board_id FROM bs); + FROM links + JOIN bs ON links.board_2 IN (SELECT board_id FROM bs) + WHERE links.live + AND NOT links.board_1 IN (SELECT board_id FROM bs); 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 6ef72a78ec..2871ac9cee 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 @@ -681,7 +681,7 @@ void deleteAllocRecord() { @Test void copyAllocsToHistoricalData() { assumeWritable(c); - try (var q = c.query(copyAllocsToHistoricalData)) { + try (var q = c.query(COPY_ALLOCS_TO_HISTORICAL_DATA)) { assertEquals(1, q.getNumArguments()); assertEquals(Set.of("alloc_id"), q.getRowColumnNames()); c.transaction(() -> { @@ -693,7 +693,7 @@ void copyAllocsToHistoricalData() { @Test void copyJobsToHistoricalData() { assumeWritable(c); - try (var q = c.query(copyJobsToHistoricalData)) { + try (var q = c.query(COPY_JOBS_TO_HISTORICAL_DATA)) { assertEquals(1, q.getNumArguments()); assertEquals(Set.of("job_id"), q.getRowColumnNames()); c.transaction(() -> { 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 4906e02454..8026b915d0 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 @@ -352,7 +352,7 @@ void getAllBoardsOfAllMachines() { @Test void getDeadLinks() { - try (var q = c.query(getDeadLinks)) { + try (var q = c.query(GET_DEAD_LINKS)) { assertEquals(1, q.getNumArguments()); assertEquals( Set.of("board_1_x", "board_1_y", "board_1_z", "board_1_c", From 3718972c2e681862368c55f974c05b58cba32920 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 16:06:03 +0000 Subject: [PATCH 021/194] Fix serialization, convert more embedded JSON to multiline strings --- .../spinnaker/messages/model/Version.java | 2 + .../spinnaker/alloc/client/JsonTest.java | 77 +++++++++++++++---- .../spalloc/messages/TestJobDescription.java | 56 ++++++++------ .../spalloc/messages/TestJobMachineInfo.java | 41 +++++++--- .../spalloc/messages/TestMachine.java | 50 +++++++++--- .../spinnaker/spalloc/messages/TestState.java | 22 ++++-- .../spalloc/messages/TestWhereIs.java | 43 ++++++++--- 7 files changed, 216 insertions(+), 75 deletions(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java index b8e5618996..cc8ea3b31f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Version.java @@ -21,6 +21,7 @@ import java.util.regex.Pattern; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -83,6 +84,7 @@ public Version(String major, String minor, String rev) { * If the version string doesn't match one of the supported * patterns. */ + @JsonCreator public static Version parse(String threePartVersion) { var m = VERSION_RE.matcher(threePartVersion); if (!m.matches()) { diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/alloc/client/JsonTest.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/alloc/client/JsonTest.java index b69895e708..8ffbecd7c5 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/alloc/client/JsonTest.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/alloc/client/JsonTest.java @@ -68,8 +68,16 @@ void jobDescription() throws Exception { @Test void jobs() throws Exception { // Deserialize only - var jobs = "{\"jobs\":[\"http:foo1\",\"http:foo2\"]," - + "\"prev\":\"http:foo3\",\"next\":\"http:foo4\"}"; + var jobs = """ + { + "jobs": [ + "http:foo1", + "http:foo2" + ], + "prev": "http:foo3", + "next": "http:foo4" + } + """; assertEquals(2, deserialize(jobs, Jobs.class).jobs.size()); } @@ -77,23 +85,56 @@ void jobs() throws Exception { void machines() throws Exception { // Deserialize only // also BriefMachineDescription, DeadLink and Direction - var ms = "{\"machines\":[{\"name\":\"foo\",\"dead-links\":[[" - + "{\"board\":{\"x\":0,\"y\":0,\"z\":0},\"direction\":0}," - + "{\"board\":{\"x\":0,\"y\":0,\"z\":0},\"direction\":1}]]}]}"; + var ms = """ + { + "machines": [ + { + "name": "foo", + "dead-links": [ + [ { + "board": { + "x": 0, + "y": 0, + "z": 0 + }, + "direction": 0 + }, { + "board": { + "x": 0, + "y": 0, + "z": 0 + }, + "direction": 1 + } ] + ] + } + ] + } + """; assertEquals(1, deserialize(ms, Machines.class).machines.size()); } @Test void power() throws Exception { - var power = "{\"power\":\"OFF\"}"; + var power = """ + { + "power": "OFF" + } + """; assertNotNull(deserialize(power, Power.class)); } @Test void rootInfo() throws Exception { - var rootInfo = "{\"csrf-header\":\"a\",\"csrf-token\":\"b\"," - + "\"jobs-uri\":\"http:c\",\"machines-uri\":\"http:d\"," - + "\"version\":\"1.2.3\"}"; + var rootInfo = """ + { + "csrf-header": "a", + "csrf-token": "b", + "jobs-uri": "http:c", + "machines-uri": "http:d", + "version": "1.2.3" + } + """; var ri = deserialize(rootInfo, RootInfo.class); assertNotNull(ri); assertEquals("a", ri.csrfHeader); @@ -105,11 +146,19 @@ void rootInfo() throws Exception { @Test void whereis() throws Exception { - var whereIs = "{\"job-id\":123,\"job-ref\":\"http:/0\"," - + "\"job-chip\":[0,0],\"chip\":[1,1]," - + "\"machine-name\":\"gorp\",\"machine-ref\":\"http:/1\"," - + "\"board-chip\":[2,2],\"logical-board-coordinates\":[0,1,2]," - + "\"physical-board-coordinates\":[3,4,5]}"; + var whereIs = """ + { + "job-id": 123, + "job-ref": "http:/0", + "job-chip": [0, 0], + "chip": [1, 1], + "machine-name": "gorp", + "machine-ref": "http:/1", + "board-chip": [2, 2], + "logical-board-coordinates": [0, 1, 2], + "physical-board-coordinates": [3, 4, 5] + } + """; var wi = deserialize(whereIs, WhereIs.class); assertNotNull(wi); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java index f11831046b..219e1e68ea 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java @@ -17,10 +17,10 @@ package uk.ac.manchester.spinnaker.spalloc.messages; import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; import java.io.IOException; +import java.util.List; import org.hamcrest.collection.IsMapContaining; import org.junit.jupiter.api.Test; @@ -34,24 +34,30 @@ public class TestJobDescription { @Test void testOneArg() throws IOException { - var json = "{\"job_id\":12345," - + "\"owner\":\"someone@manchester.ac.uk\"," - + "\"start_time\":1.537284307847865E9," - + "\"keepalive\":45.0," - + "\"state\":3," - + "\"power\":true," - + "\"args\":[1]," - + "\"kwargs\":{" + ( - "\"tags\":null," - + "\"max_dead_boards\":0," - + "\"machine\":null," - + "\"min_ratio\":0.333," - + "\"max_dead_links\":null," - + "\"require_torus\":false" - ) + "}," - + "\"allocated_machine_name\":\"Spin24b-223\"," - + "\"boards\":[[1,1,2]]," - + "\"keepalivehost\":\"130.88.198.171\"}"; + var json = """ + { + "job_id": 12345, + "owner": "someone@manchester.ac.uk", + "start_time": 1.537284307847865E9, + "keepalive": 45.0, + "state": 3, + "power": true, + "args": [1], + "kwargs": { + "tags": null, + "max_dead_boards": 0, + "machine": null, + "min_ratio": 0.333, + "max_dead_links": null, + "require_torus": false + }, + "allocated_machine_name": "Spin24b-223", + "boards": [ + [1, 1, 2] + ], + "keepalivehost": "130.88.198.171" + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobDescription.class); @@ -61,7 +67,7 @@ void testOneArg() throws IOException { assertEquals(45, fromJson.getKeepAlive()); assertEquals(State.values()[3], fromJson.getState()); assertEquals(true, fromJson.getPower()); - assertThat(fromJson.getArgs(), contains(1)); + assertEquals(List.of(1), fromJson.getArgs()); var map = fromJson.getKwargs(); assertThat(map, IsMapContaining.hasEntry("tags", null)); assertThat(map, IsMapContaining.hasEntry("max_dead_boards", 0)); @@ -70,14 +76,18 @@ void testOneArg() throws IOException { assertThat(map, IsMapContaining.hasEntry("max_dead_links", null)); assertThat(map, IsMapContaining.hasEntry("require_torus", false)); assertEquals("Spin24b-223", fromJson.getMachine()); - assertThat(fromJson.getBoards(), - contains(new BoardCoordinates(1, 1, 2))); + assertEquals(List.of(new BoardCoordinates(1, 1, 2)), + fromJson.getBoards()); assertEquals("130.88.198.171", fromJson.getKeepAliveHost()); } @Test void testNulls() throws IOException { - var json = "{\"job_id\":null}"; + var json = """ + { + "job_id": null + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobDescription.class); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java index ee4da69e28..1a7df61e51 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java @@ -33,14 +33,29 @@ public class TestJobMachineInfo { @Test void testFromJson() throws IOException { - var json = "{\"connections\":[[[0,0],\"10.2.225.177\"]," - + "[[4,8],\"10.2.225.145\"],[[0,12],\"10.2.225.185\"]," - + "[[8,16],\"10.2.225.121\"],[[4,20],\"10.2.225.153\"]," - + "[[8,4],\"10.2.225.113\"]]," - + "\"width\":16,\"machine_name\":\"Spin24b-001\"," - + "\"boards\":" - + "[[2,1,1],[2,1,0],[2,1,2],[2,0,2],[2,0,1],[2,0,0]]," - + "\"height\":24}"; + var json = """ + { + "connections": [ + [[0,0], "10.2.225.177"], + [[4,8], "10.2.225.145"], + [[0,12], "10.2.225.185"], + [[8,16], "10.2.225.121"], + [[4,20], "10.2.225.153"], + [[8,4], "10.2.225.113"] + ], + "width": 16, + "machine_name": "Spin24b-001", + "boards": [ + [2,1,1], + [2,1,0], + [2,1,2], + [2,0,2], + [2,0,1], + [2,0,0] + ], + "height": 24 + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobMachineInfo.class); assertEquals(6, fromJson.getConnections().size()); @@ -52,9 +67,13 @@ void testFromJson() throws IOException { @Test void testNullJson() throws IOException { - var json = "{\"connections\":null," - + "\"machine_name\":null," - + "\"boards\":null}"; + var json = """ + { + "connections": null, + "machine_name": null, + "boards": null + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobMachineInfo.class); assertEquals(0, fromJson.getConnections().size()); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java index a6f9a9aeeb..311ca5f93d 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java @@ -34,10 +34,22 @@ public class TestMachine { @Test void testFromJson() throws IOException { - var json = "{\"name\":\"power-monitor\"," - + "\"tags\":[\"power-monitor\",\"machine-room\"]," - + "\"width\":1,\"height\":1," - + "\"dead_boards\":[[0,0,1],[0,0,2]],\"dead_links\":[]}"; + var json = """ + { + "name": "power-monitor", + "tags": [ + "power-monitor", + "machine-room" + ], + "width": 1, + "height":1, + "dead_boards":[ + [0,0,1], + [0,0,2] + ], + "dead_links": [] + }" + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, Machine.class); assertEquals("power-monitor", fromJson.getName()); @@ -53,11 +65,25 @@ void testFromJson() throws IOException { @Test void testAssumedDeadLinks() throws IOException { - var json = "{\"name\":\"power-monitor\"," - + "\"tags\":[\"power-monitor\",\"machine-room\"]," - + "\"width\":1,\"height\":1," - + "\"dead_boards\":[[1,2,3],[4,5,6]]," - + "\"dead_links\":[[7,8,9,10],[11,12,13,14]]}"; + var json = """ + { + "name": "power-monitor", + "tags": [ + "power-monitor", + "machine-room" + ], + "width": 1, + "height": 1, + "dead_boards": [ + [1,2,3], + [4,5,6] + ], + "dead_links": [ + [7,8,9,10], + [11,12,13,14] + ] + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, Machine.class); assertEquals("power-monitor", fromJson.getName()); @@ -75,7 +101,11 @@ void testAssumedDeadLinks() throws IOException { @Test void testNullJson() throws IOException { - var json = "{\"name\":null}"; + var json = """ + { + "name": null + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, Machine.class); assertNull(fromJson.getName()); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java index 6a60741670..b407078d88 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java @@ -32,12 +32,16 @@ public class TestState { @Test void testFromJson() throws IOException { - var json = "{\"state\":2," - + "\"power\":true," - + "\"keepalive\":60.0," - + "\"reason\":null," - + "\"start_time\":1.125," - + "\"keepalivehost\":\"86.82.216.229\"}"; + var json = """ + { + "state": 2, + "power": true, + "keepalive": 60.0, + "reason": null, + "start_time": 1.125, + "keepalivehost": "86.82.216.229" + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobState.class); assertEquals(State.POWER, fromJson.getState()); @@ -51,7 +55,11 @@ void testFromJson() throws IOException { @Test void testNullJson() throws IOException { - var json = "{\"reason\":null}"; + var json = """ + { + "reason": null + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, JobState.class); assertNull(fromJson.getState()); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java index bf9b53d3a3..05f82c2d79 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java @@ -39,9 +39,17 @@ void testFromJson() throws IOException { var logical = new BoardCoordinates(5, 6, 7); var physical = new BoardPhysicalCoordinates(10, 11, 12); - var json = "{\"job_chip\":[1,2],\"job_id\":666,\"chip\":[3,4]," - + "\"logical\":[5,6,7],\"machine\":\"Spin24b-001\"," - + "\"board_chip\":[8,9],\"physical\":[10,11,12]}"; + var json = """ + { + "job_chip": [1,2], + "job_id": 666, + "chip": [3,4], + "logical": [5,6,7], + "machine": "Spin24b-001", + "board_chip": [8,9], + "physical": [10,11,12] + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); assertEquals(jobChip, fromJson.jobChip()); @@ -67,9 +75,17 @@ void testBug() throws IOException { var logical = new BoardCoordinates(0, 0, 1); var physical = new BoardPhysicalCoordinates(0, 0, 8); - var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":[8,4]," - + "\"logical\":[0,0,1],\"machine\":\"Spin24b-001\"," - + "\"board_chip\":[0,0],\"physical\":[0,0,8]}"; + var json = """ + { + "job_chip": null, + "job_id": null, + "chip": [8,4], + "logical": [0,0,1], + "machine": "Spin24b-001", + "board_chip": [0,0], + "physical": [0,0,8] + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); assertNull(fromJson.jobChip()); @@ -89,10 +105,17 @@ void testBug() throws IOException { @Test void testNulls() throws IOException { - - var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":null," - + "\"logical\":null,\"machine\":null,\"board_chip\":null," - + "\"physical\":null}"; + var json = """ + { + "job_chip": null, + "job_id": null, + "chip": null, + "logical": null, + "machine": null, + "board_chip": null, + "physical": null + } + """; var mapper = SpallocClient.createMapper(); var fromJson = mapper.readValue(json, WhereIs.class); assertNull(fromJson.jobChip()); From 56452720b8bc456a4d73858548492e363048a791 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 12 Dec 2022 17:09:19 +0000 Subject: [PATCH 022/194] Records and TYPE_USE annotations interact weirdly It looks like I've hit a Java bug, albeit one I can work around easily --- .../alloc/admin/MachineDefinitionLoader.java | 13 ++++--- .../spinnaker/alloc/admin/MDefLoaderTest.java | 15 +++++++- .../test/resources/bad-board-example2.json | 36 +++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 SpiNNaker-allocserv/src/test/resources/bad-board-example2.json diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index d072ed167a..e79dafa687 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -440,10 +440,15 @@ public Machine build() { * Time to wait before freeing. (Ignored) */ public record Configuration(// - @NotNull List<@Valid Machine> machines, @TCPPort int port, - @IPAddress(nullOK = true, emptyOK = true) String ip, - @Positive double timeoutCheckInterval, @Positive int maxRetiredJobs, - @Positive int secondsBeforeFree) { + @JsonProperty("machines") @NotNull @Valid List machines, + @JsonProperty("port") @TCPPort int port, + @JsonProperty("ip") @IPAddress(nullOK = true, emptyOK = true) // + String ip, // + @JsonProperty("timeout-check-interval") @Positive // + double timeoutCheckInterval, + @JsonProperty("max-retired-jobs") @Positive int maxRetiredJobs, + @JsonProperty("seconds-before-free") @Positive // + double secondsBeforeFree) { @Override public String toString() { return new StringBuilder("Configuration(").append("machines=") 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 d441a98813..64624fee89 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 @@ -71,6 +71,9 @@ class MDefLoaderTest extends MemDBTestBase { @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()); @@ -89,7 +92,7 @@ void readSingleBoardExample() throws IOException { } @Test - void readBadBoardExample() throws IOException { + void readBadBoardExample() { var e = assertThrows(IOException.class, () -> loader.readMachineDefinitions(badBoard.getFile())); assertEquals( @@ -98,6 +101,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/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 +} From c2082030fc8090a1bafcbe7b1c3d2341edd25316 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 13 Dec 2022 09:59:35 +0000 Subject: [PATCH 023/194] Subtleties in serialization --- .../alloc/admin/MachineDefinitionLoader.java | 2 +- .../alloc/model/BoardIssueReport.java | 10 ++++------ .../spinnaker/alloc/web/CreateJobRequest.java | 20 +++++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index e79dafa687..2cf293ad35 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -440,7 +440,7 @@ public Machine build() { * Time to wait before freeing. (Ignored) */ public record Configuration(// - @JsonProperty("machines") @NotNull @Valid List machines, + @JsonProperty("machines") @NotNull List<@Valid Machine> machines, @JsonProperty("port") @TCPPort int port, @JsonProperty("ip") @IPAddress(nullOK = true, emptyOK = true) // String ip, // 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 990c2799f7..785d619429 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 @@ -16,12 +16,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; @@ -42,12 +40,12 @@ * @param timestamp * When was it reported? */ -@JsonAutoDetect(setterVisibility = NON_PRIVATE) public record BoardIssueReport(int id, int boardId, String issue, String reporter, Instant timestamp) { @JsonCreator - BoardIssueReport(int id, int boardId, String issue, String reporter, - String timestamp) { + BoardIssueReport(@JsonProperty int id, @JsonProperty int boardId, + @JsonProperty String issue, @JsonProperty String reporter, + @JsonProperty String timestamp) { this(id, boardId, issue, reporter, Instant.parse(timestamp)); } 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 d8fc35c120..ae4e16eea4 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 @@ -31,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.errorprone.annotations.Keep; import uk.ac.manchester.spinnaker.machine.board.ValidBoardNumber; @@ -93,16 +94,19 @@ public record CreateJobRequest(String owner, String group, @PositiveOrZero(message = "max-dead-boards may not be " + "negative") Integer maxDeadBoards) { @JsonCreator - CreateJobRequest(String owner, String group, - @NotNull(message = "keepalive-interval is " + CreateJobRequest(@JsonProperty String owner, @JsonProperty String group, + @JsonProperty @NotNull(message = "keepalive-interval is " + "required") String keepaliveInterval, - @Positive(message = "number of boards must be " + @JsonProperty @Positive(message = "number of boards must be " + "at least 1 if given") Integer numBoards, - @Valid Dimensions dimensions, @Valid SpecificBoard board, - String machineName, - List<@NotBlank(message = "tags must not be blank") String> tags, - @PositiveOrZero(message = "max-dead-boards may not be " - + "negative") Integer maxDeadBoards) { + @JsonProperty @Valid Dimensions dimensions, + @JsonProperty @Valid SpecificBoard board, + @JsonProperty String machineName, + @JsonProperty List< + @NotBlank(message = "tags must not be blank") String> tags, + @JsonProperty @PositiveOrZero(// + message = "max-dead-boards may not be negative") // + Integer maxDeadBoards) { this(owner, group, Duration.parse(keepaliveInterval), numBoards, dimensions, board, machineName, tags, maxDeadBoards); } From 55117587ed15c23da675e97849b1b3e58fd7b06d Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 13 Dec 2022 16:31:01 +0000 Subject: [PATCH 024/194] Grr! --- .../spinnaker/alloc/ServiceConfig.java | 4 ++ .../alloc/admin/MachineDefinitionLoader.java | 2 +- .../alloc/compat/V1CompatService.java | 5 ++- .../spinnaker/alloc/web/CreateJobRequest.java | 39 ++++++------------- .../spinnaker/alloc/compat/JsonTest.java | 4 ++ .../spinnaker/alloc/web/JsonTest.java | 4 ++ pom.xml | 3 ++ 7 files changed, 32 insertions(+), 29 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java index ec5c38ddfd..a2ec076d6f 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java @@ -76,6 +76,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 com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AllocatorProperties; @@ -145,6 +147,8 @@ ScheduledExecutorService scheduledThreadPoolExecutor( @Role(ROLE_INFRASTRUCTURE) JsonMapper mapper() { return JsonMapper.builder().findAndAddModules() + .addModule(new JavaTimeModule()) + .addModule(new Jdk8Module()) .disable(WRITE_DATES_AS_TIMESTAMPS) .propertyNamingStrategy(KEBAB_CASE).build(); } diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 2cf293ad35..e79dafa687 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -440,7 +440,7 @@ public Machine build() { * Time to wait before freeing. (Ignored) */ public record Configuration(// - @JsonProperty("machines") @NotNull List<@Valid Machine> machines, + @JsonProperty("machines") @NotNull @Valid List machines, @JsonProperty("port") @TCPPort int port, @JsonProperty("ip") @IPAddress(nullOK = true, emptyOK = true) // String ip, // 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 cb5d6d773e..4d770264a0 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 @@ -47,6 +47,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 com.google.errorprone.annotations.RestrictedApi; import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; @@ -96,7 +98,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 -> { 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 ae4e16eea4..9ebaeef8a1 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 @@ -29,7 +29,6 @@ import javax.validation.constraints.Positive; import javax.validation.constraints.PositiveOrZero; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.errorprone.annotations.Keep; @@ -83,34 +82,20 @@ * allocation. Note that the allocation engine might increase this if * it decides to overallocate. Defaults to {@code 0}. */ -public record CreateJobRequest(String owner, String group, +public record CreateJobRequest(@JsonProperty String owner, + @JsonProperty String group, + @JsonProperty("keepalive-interval") @NotNull(message = "keepalive-interval is " + "required") Duration keepaliveInterval, - @Positive(message = "number of boards must be " - + "at least 1 if given") Integer numBoards, - @Valid Dimensions dimensions, @Valid SpecificBoard board, - String machineName, - List<@NotBlank(message = "tags must not be blank") String> tags, - @PositiveOrZero(message = "max-dead-boards may not be " - + "negative") Integer maxDeadBoards) { - @JsonCreator - CreateJobRequest(@JsonProperty String owner, @JsonProperty String group, - @JsonProperty @NotNull(message = "keepalive-interval is " - + "required") String keepaliveInterval, - @JsonProperty @Positive(message = "number of boards must be " - + "at least 1 if given") Integer numBoards, - @JsonProperty @Valid Dimensions dimensions, - @JsonProperty @Valid SpecificBoard board, - @JsonProperty String machineName, - @JsonProperty List< - @NotBlank(message = "tags must not be blank") String> tags, - @JsonProperty @PositiveOrZero(// - message = "max-dead-boards may not be negative") // - Integer maxDeadBoards) { - this(owner, group, Duration.parse(keepaliveInterval), numBoards, - dimensions, board, machineName, tags, maxDeadBoards); - } - + @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 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 4e238f790f..6fde3fc312 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 @@ -31,6 +31,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; @@ -49,6 +51,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(); } 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 ad1edb5442..43dc055411 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 @@ -43,6 +43,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.alloc.allocator.SpallocAPI.BoardLocation; import uk.ac.manchester.spinnaker.alloc.allocator.SpallocAPI.Job; @@ -63,6 +65,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(); } diff --git a/pom.xml b/pom.xml index afaa559f90..25ac2b0910 100644 --- a/pom.xml +++ b/pom.xml @@ -354,6 +354,9 @@ along with this program. If not, see . org.apache.maven.plugins maven-compiler-plugin 3.10.1 + + true + org.apache.maven.plugins From da7df63d0f08fdd6507b53be2db2a73f9266e90d Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 14 Dec 2022 12:24:58 +0000 Subject: [PATCH 025/194] More records and sealing --- .../alloc/admin/MachineStateControl.java | 20 +- .../spinnaker/alloc/allocator/Spalloc.java | 6 +- .../spinnaker/alloc/allocator/SpallocAPI.java | 16 +- .../spinnaker/alloc/bmp/SpiNNaker1.java | 2 +- .../spinnaker/alloc/proxy/ProxyCore.java | 44 ++--- .../spinnaker/alloc/client/BoardCoords.java | 185 +++++------------- .../spinnaker/spalloc/messages/Command.java | 10 +- .../spalloc/messages/CreateJobCommand.java | 2 +- .../spalloc/messages/CustomIntCommand.java | 38 ++++ .../spalloc/messages/CustomStringCommand.java | 38 ++++ .../spalloc/messages/DestroyJobCommand.java | 2 +- .../spalloc/messages/ExceptionResponse.java | 2 +- .../messages/GetBoardAtPositionCommand.java | 2 +- .../messages/GetBoardPositionCommand.java | 2 +- .../messages/GetJobMachineInfoCommand.java | 2 +- .../spalloc/messages/GetJobStateCommand.java | 2 +- .../spalloc/messages/JobKeepAliveCommand.java | 2 +- .../messages/JobsChangedNotification.java | 2 +- .../spalloc/messages/ListJobsCommand.java | 2 +- .../spalloc/messages/ListMachinesCommand.java | 2 +- .../messages/MachinesChangedNotification.java | 2 +- .../spalloc/messages/NoNotifyJobCommand.java | 2 +- .../messages/NoNotifyMachineCommand.java | 2 +- .../spalloc/messages/Notification.java | 3 +- .../spalloc/messages/NotifyJobCommand.java | 2 +- .../messages/NotifyMachineCommand.java | 2 +- .../messages/PowerOffJobBoardsCommand.java | 2 +- .../messages/PowerOnJobBoardsCommand.java | 2 +- .../spinnaker/spalloc/messages/Response.java | 3 +- .../spalloc/messages/ReturnResponse.java | 2 +- .../spalloc/messages/VersionCommand.java | 2 +- .../messages/WhereIsJobChipCommand.java | 2 +- .../WhereIsMachineBoardLogicalCommand.java | 2 +- .../WhereIsMachineBoardPhysicalCommand.java | 2 +- .../messages/WhereIsMachineChipCommand.java | 2 +- .../spinnaker/transceiver/TxrxProcess.java | 11 +- .../spinnaker/spalloc/TestClient.java | 25 ++- .../front_end/download/DataGatherer.java | 5 +- .../download/DirectDataGatherer.java | 2 +- .../download/RecordingRegionDataGatherer.java | 2 +- .../front_end/iobuf/TestReplacer.java | 2 + 41 files changed, 224 insertions(+), 236 deletions(-) create mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java create mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index 18f7c04c01..1ec97d3ea4 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -534,7 +534,7 @@ private void readAllBoardSerialNumbers() { private void scheduleSerialNumberReads(String machineName) { batchReqs(machineName, "retrieving serial numbers", props.getSerialReadBatchSize(), - id -> new Op(CREATE_SERIAL_READ_REQ, id), Op::completed); + id -> new BmpOp(CREATE_SERIAL_READ_REQ, id), BmpOp::completed); } private interface InterruptableConsumer { @@ -568,8 +568,8 @@ private interface InterruptableConsumer { * How to process the results of an individual operation. */ private void batchReqs(String machineName, String action, int batchSize, - Function opGenerator, - InterruptableConsumer opResultsHandler) { + Function opGenerator, + InterruptableConsumer opResultsHandler) { var boards = executeRead(c -> listAllBoards(c, machineName)); for (var batch : batch(batchSize, boards)) { /* @@ -592,7 +592,7 @@ private void batchReqs(String machineName, String action, int batchSize, } } } finally { - ops.forEach(Op::close); + ops.forEach(BmpOp::close); } if (stop) { // Mark as interrupted @@ -612,7 +612,7 @@ private void batchReqs(String machineName, String action, int batchSize, public void updateAllBlacklists(@NotBlank String machineName) { batchReqs(requireNonNull(machineName), "retrieving blacklists", props.getBlacklistReadBatchSize(), - id -> new Op(CREATE_BLACKLIST_READ, id), + id -> new BmpOp(CREATE_BLACKLIST_READ, id), op -> op.getResult(serial("data", Blacklist.class)) .ifPresent(bl -> { blacklistStore.writeBlacklist(op.boardId, bl); @@ -684,7 +684,7 @@ public void writeBlacklistToDB(BoardState board, */ public Optional readBlacklistFromMachine(BoardState board) throws InterruptedException { - try (var op = new Op(CREATE_BLACKLIST_READ, board.id)) { + try (var op = new BmpOp(CREATE_BLACKLIST_READ, board.id)) { return op.getResult(serial("data", Blacklist.class)); } } @@ -706,7 +706,7 @@ public Optional readBlacklistFromMachine(BoardState board) */ public void writeBlacklistToMachine(BoardState board, @Valid Blacklist blacklist) throws InterruptedException { - try (var op = new Op(CREATE_BLACKLIST_WRITE, board.id, blacklist)) { + try (var op = new BmpOp(CREATE_BLACKLIST_WRITE, board.id, blacklist)) { op.completed(); } } @@ -726,7 +726,7 @@ public void writeBlacklistToMachine(BoardState board, */ public String getSerialNumber(BoardState board) throws InterruptedException { - try (var op = new Op(CREATE_SERIAL_READ_REQ, board.id)) { + try (var op = new BmpOp(CREATE_SERIAL_READ_REQ, board.id)) { op.completed(); } // Can now read out of the DB normally @@ -756,7 +756,7 @@ public boolean isBlacklistSynched(BoardState board) { * * @author Donal Fellows */ - private final class Op implements AutoCloseable { + private final class BmpOp implements AutoCloseable { private final int op; private final Epoch epoch; @@ -772,7 +772,7 @@ private final class Op implements AutoCloseable { */ @MustBeClosed @SuppressWarnings("CompileTimeConstant") - Op(@CompileTimeConstant final String operation, Object... args) { + BmpOp(@CompileTimeConstant final String operation, Object... args) { boardId = ((Integer) args[0]).intValue(); // TODO yuck! epoch = epochs.getBlacklistEpoch(); op = execute(conn -> { 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 7116499e6c..f4ad25655c 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 @@ -207,7 +207,7 @@ private Optional getMachine(String name, } } - private class DescribeMachineSQL extends AbstractSQL { + private final class DescribeMachineSQL extends AbstractSQL { final Query namedMachine = conn.query(GET_NAMED_MACHINE); final Query countMachineThings = conn.query(COUNT_MACHINE_THINGS); @@ -710,7 +710,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; @@ -924,7 +924,7 @@ public String toString() { } } - private class JobCollection implements Jobs { + private final class JobCollection implements Jobs { @JsonIgnore private Epoch epoch; 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 a32770bce8..4e39f62fb6 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 @@ -671,7 +671,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. @@ -680,7 +682,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. @@ -689,7 +693,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. @@ -698,7 +704,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/SpiNNaker1.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/SpiNNaker1.java index dc613b1928..1aba02af09 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 @@ -156,7 +156,7 @@ private List remap(List boardIds) { } /** 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; 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 881371fe4b..b945873ca3 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 @@ -45,7 +45,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 @@ -119,21 +118,13 @@ 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; + }; } /** @@ -258,19 +249,19 @@ protected ByteBuffer openUnconnectedChannel(ByteBuffer message) // This method handles message parsing/assembly and validation int corId = message.getInt(); - var localAddress = new ValueHolder(); - var localPort = new ValueHolder(); - int id = openUnconnected(localAddress, localPort); + var result = openUnconnected(); var msg = response(OPEN_UNCONNECTED, corId); - msg.putInt(id); - msg.put(localAddress.getValue().getAddress()); - msg.putInt(localPort.getValue()); + msg.putInt(result.id); + msg.put(result.localAddr.getAddress()); + msg.putInt(result.localPort); return msg; } - private int openUnconnected(ValueHolder localAddress, - ValueHolder localPort) throws IOException { + private record Unconnected(int id, InetAddress localAddr, int localPort) { + } + + private Unconnected openUnconnected() throws IOException { if (localHost == null) { throw new IOException( "cannot receive if localHost is not definite"); @@ -287,10 +278,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-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 077d621832..850350bfb1 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 @@ -18,11 +18,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; @@ -31,151 +32,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; + @JsonIgnore + public PhysicalCoords physicalCoords() { + if (board == null) { + return null; + } + return new PhysicalCoords(cabinet, frame, board); } @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) { - return (other instanceof BoardCoords o) && (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); - } - - @Override - public int hashCode() { - return (x << 16) | (y << 8) | z; + 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/spalloc/messages/Command.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Command.java index bd8c430549..e5f5b0f471 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Command.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Command.java @@ -28,7 +28,15 @@ * @param * The type of arguments. */ -public abstract class Command { +public abstract sealed class Command // + permits CreateJobCommand, DestroyJobCommand, GetBoardAtPositionCommand, + GetBoardPositionCommand, GetJobMachineInfoCommand, GetJobStateCommand, + JobKeepAliveCommand, ListJobsCommand, ListMachinesCommand, + NoNotifyJobCommand, NoNotifyMachineCommand, NotifyJobCommand, + NotifyMachineCommand, PowerOffJobBoardsCommand, PowerOnJobBoardsCommand, + VersionCommand, WhereIsJobChipCommand, + WhereIsMachineBoardLogicalCommand, WhereIsMachineBoardPhysicalCommand, + WhereIsMachineChipCommand, CustomIntCommand, CustomStringCommand { private final String command; private final List args = new ArrayList<>(); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CreateJobCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CreateJobCommand.java index a0e363883a..185d015d55 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CreateJobCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CreateJobCommand.java @@ -26,7 +26,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.create_job" * >Spalloc Server documentation */ -public class CreateJobCommand extends Command { +public final class CreateJobCommand extends Command { /** * Create a request to create a job. Short-hand form for most basic kind of * request. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java new file mode 100644 index 0000000000..1404b8c688 --- /dev/null +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package uk.ac.manchester.spinnaker.spalloc.messages; + +/** + * A custom command not part of the standard protocol. These are not + * guaranteed to be accepted by any spalloc service. + */ +public abstract non-sealed class CustomIntCommand extends Command { + /** + * Create a command. + * + * @param name + * The name of the command. + * @param args + * The integer positional arguments. + */ + public CustomIntCommand(String name, int... args) { + super(name); + for (int arg : args) { + addArg(arg); + } + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java new file mode 100644 index 0000000000..a46573f86b --- /dev/null +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package uk.ac.manchester.spinnaker.spalloc.messages; + +/** + * A custom command not part of the standard protocol. These are not + * guaranteed to be accepted by any spalloc service. + */ +public abstract non-sealed class CustomStringCommand extends Command { + /** + * Create a command. + * + * @param name + * The name of the command. + * @param args + * The string positional arguments. + */ + public CustomStringCommand(String name, String... args) { + super(name); + for (var arg : args) { + addArg(arg); + } + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/DestroyJobCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/DestroyJobCommand.java index f1e2079668..aa402fed4a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/DestroyJobCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/DestroyJobCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.destroy_job" * >Spalloc Server documentation */ -public class DestroyJobCommand extends Command { +public final class DestroyJobCommand extends Command { /** * Make a request to destroy a job. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ExceptionResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ExceptionResponse.java index a534e23b4a..6b3d64c73c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ExceptionResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ExceptionResponse.java @@ -24,7 +24,7 @@ * A response to a request that indicates a failure. */ @JsonAutoDetect(setterVisibility = NON_PRIVATE) -public class ExceptionResponse implements Response { +public final class ExceptionResponse implements Response { private String exception; /** @return The exception message. Should not include a stack trace. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java index 550082b9ee..32839ad019 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java @@ -29,7 +29,7 @@ * >Spalloc Server documentation * @see BoardCoordinates The basic result type associated with the request */ -public class GetBoardAtPositionCommand extends Command { +public final class GetBoardAtPositionCommand extends Command { /** * Create a request. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java index 9147949a74..c9b8a657ca 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java @@ -30,7 +30,7 @@ * @see BoardPhysicalCoordinates The basic result type associated with the * request */ -public class GetBoardPositionCommand extends Command { +public final class GetBoardPositionCommand extends Command { /** * Create a request. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobMachineInfoCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobMachineInfoCommand.java index 5b81dac5d3..d511a970d2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobMachineInfoCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobMachineInfoCommand.java @@ -24,7 +24,7 @@ * >Spalloc Server documentation * @see JobMachineInfo The basic result type associated with the request */ -public class GetJobMachineInfoCommand extends Command { +public final class GetJobMachineInfoCommand extends Command { /** * Create a request to get information about a job's allocated machine. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobStateCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobStateCommand.java index 51241c2781..73d41f8d50 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobStateCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetJobStateCommand.java @@ -24,7 +24,7 @@ * >Spalloc Server documentation * @see JobState The basic result type associated with the request */ -public class GetJobStateCommand extends Command { +public final class GetJobStateCommand extends Command { /** * Create a request to get the state of a job. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobKeepAliveCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobKeepAliveCommand.java index b7d2ff9778..5fecb95324 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobKeepAliveCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobKeepAliveCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.job_keepalive" * >Spalloc Server documentation */ -public class JobKeepAliveCommand extends Command { +public final class JobKeepAliveCommand extends Command { /** * Create a request to keep a job alive. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java index 9dadebdfbe..3574759e71 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobsChangedNotification.java @@ -27,7 +27,7 @@ * A response that describes what jobs have changed state. */ @JsonAutoDetect(setterVisibility = NON_PRIVATE) -public class JobsChangedNotification implements Notification { +public final class JobsChangedNotification implements Notification { private List jobsChanged = List.of(); /** Create a notification response. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListJobsCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListJobsCommand.java index c0cfd0657c..49900eb743 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListJobsCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListJobsCommand.java @@ -24,7 +24,7 @@ * >Spalloc Server documentation * @see JobDescription The basic result type associated with the request */ -public class ListJobsCommand extends Command { +public final class ListJobsCommand extends Command { /** * Create a request to list the jobs. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListMachinesCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListMachinesCommand.java index a79644c9fc..263a800658 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListMachinesCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ListMachinesCommand.java @@ -24,7 +24,7 @@ * >Spalloc Server documentation * @see Machine The basic result type associated with the request */ -public class ListMachinesCommand extends Command { +public final class ListMachinesCommand extends Command { /** Create a request to list the known SpiNNaker machines. */ public ListMachinesCommand() { super("list_machines"); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/MachinesChangedNotification.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/MachinesChangedNotification.java index 0e91d8454d..8fcf588b83 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/MachinesChangedNotification.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/MachinesChangedNotification.java @@ -27,7 +27,7 @@ * A response that describes what machines have changed state. */ @JsonAutoDetect(setterVisibility = NON_PRIVATE) -public class MachinesChangedNotification implements Notification { +public final class MachinesChangedNotification implements Notification { private List machinesChanged = List.of(); /** @return What machines have changed. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyJobCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyJobCommand.java index be7b820da3..ff9255736b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyJobCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyJobCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.no_notify_job" * >Spalloc Server documentation */ -public class NoNotifyJobCommand extends Command { +public final class NoNotifyJobCommand extends Command { /** * Create a request to not be notified of changes in job state. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyMachineCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyMachineCommand.java index 97b2961a29..0a35116cc4 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyMachineCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NoNotifyMachineCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.no_notify_machine" * >Spalloc Server documentation */ -public class NoNotifyMachineCommand extends Command { +public final class NoNotifyMachineCommand extends Command { // /** * Create a request to not be notified of changes in machine state. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Notification.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Notification.java index 80a63a11aa..4db6629eb5 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Notification.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Notification.java @@ -20,6 +20,7 @@ * Notifications all implement. They are not sent in response to specific * requests unlike ordinary {@linkplain Response responses}. */ -public interface Notification extends Response { +public sealed interface Notification extends Response + permits JobsChangedNotification, MachinesChangedNotification { // empty } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyJobCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyJobCommand.java index 106b653084..a41032b6d5 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyJobCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyJobCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.notify_job" * >Spalloc Server documentation */ -public class NotifyJobCommand extends Command { +public final class NotifyJobCommand extends Command { /** * Create a request to be notified of changes in job state. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyMachineCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyMachineCommand.java index b9f9d90c17..197380cd65 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyMachineCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/NotifyMachineCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.notify_machine" * >Spalloc Server documentation */ -public class NotifyMachineCommand extends Command { +public final class NotifyMachineCommand extends Command { /** * Create a request to be notified of changes in machine state. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOffJobBoardsCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOffJobBoardsCommand.java index e7977d1762..71f809a15b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOffJobBoardsCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOffJobBoardsCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.power_off_job_boards" * >Spalloc Server documentation */ -public class PowerOffJobBoardsCommand extends Command { +public final class PowerOffJobBoardsCommand extends Command { /** * Create a request to turn off a job's allocated boards. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOnJobBoardsCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOnJobBoardsCommand.java index 0eea3e08b7..4b938ed063 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOnJobBoardsCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/PowerOnJobBoardsCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.power_on_job_boards" * >Spalloc Server documentation */ -public class PowerOnJobBoardsCommand extends Command { +public final class PowerOnJobBoardsCommand extends Command { /** * Create a request to turn on a job's allocated boards. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Response.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Response.java index c5eac147d6..e2a1285a3a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Response.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Response.java @@ -19,6 +19,7 @@ /** * An (abstract) response from the machine manager. Responses are all POJOs. */ -public interface Response { +public sealed interface Response + permits ExceptionResponse, Notification, ReturnResponse { // Does Nothing } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ReturnResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ReturnResponse.java index 6e29846be3..d8d2e68dc4 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ReturnResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/ReturnResponse.java @@ -22,7 +22,7 @@ /** * A response that is the successful result of a request. */ -public class ReturnResponse implements Response { +public final class ReturnResponse implements Response { private String returnValue; /** @return The returned value, as a string. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/VersionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/VersionCommand.java index de5f2950c6..3ddf021c9a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/VersionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/VersionCommand.java @@ -23,7 +23,7 @@ * "https://spalloc-server.readthedocs.io/en/stable/protocol/#commands.version" * >Spalloc Server documentation */ -public class VersionCommand extends Command { +public final class VersionCommand extends Command { /** * Create a request to get the version of the spalloc server. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsJobChipCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsJobChipCommand.java index 8c73869440..fb9a4eef22 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsJobChipCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsJobChipCommand.java @@ -27,7 +27,7 @@ * >Spalloc Server documentation * @see WhereIs The basic result type associated with the request */ -public class WhereIsJobChipCommand extends Command { +public final class WhereIsJobChipCommand extends Command { /** * Create a request to locate a chip within a job's allocation. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java index 584339c78b..d353b01d3b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java @@ -29,7 +29,7 @@ * >Spalloc Server documentation * @see WhereIs The basic result type associated with the request */ -public class WhereIsMachineBoardLogicalCommand extends Command { +public final class WhereIsMachineBoardLogicalCommand extends Command { /** * Create a request to locate a board on a machine. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java index 55a19736af..aa0dfec5b3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java @@ -30,7 +30,7 @@ * >Spalloc Server documentation * @see WhereIs The basic result type associated with the request */ -public class WhereIsMachineBoardPhysicalCommand extends Command { +public final class WhereIsMachineBoardPhysicalCommand extends Command { /** * Create a request to locate a board on a machine. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineChipCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineChipCommand.java index 437ebaf313..d390041ca6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineChipCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineChipCommand.java @@ -26,7 +26,7 @@ * >Spalloc Server documentation * @see WhereIs The basic result type associated with the request */ -public class WhereIsMachineChipCommand extends Command { +public final class WhereIsMachineChipCommand extends Command { /** * Create a request to locate a chip on a machine. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java index 12daaef70d..3b44217931 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java @@ -330,16 +330,7 @@ protected final void sendOneWayRequest(SCPRequest request) * States that a particular request failed with a particular exception. The * request should not be retried once this has been generated. */ - // TODO make into a record once on a new enough language profile - private static class Failure { - private final SCPRequest req; - - private final Exception exn; - - Failure(SCPRequest req, Exception exn) { - this.req = req; - this.exn = exn; - } + private record Failure(SCPRequest req, Exception exn) { } /** diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java index 4f018fa0b0..e4d3290aed 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java @@ -39,7 +39,7 @@ import uk.ac.manchester.spinnaker.spalloc.exceptions.SpallocServerException; import uk.ac.manchester.spinnaker.spalloc.messages.BoardCoordinates; import uk.ac.manchester.spinnaker.spalloc.messages.BoardPhysicalCoordinates; -import uk.ac.manchester.spinnaker.spalloc.messages.Command; +import uk.ac.manchester.spinnaker.spalloc.messages.CustomIntCommand; import uk.ac.manchester.spinnaker.spalloc.messages.ExceptionResponse; import uk.ac.manchester.spinnaker.spalloc.messages.JobsChangedNotification; import uk.ac.manchester.spinnaker.spalloc.messages.MachinesChangedNotification; @@ -48,11 +48,10 @@ import uk.ac.manchester.spinnaker.spalloc.messages.WhereIs; class TestClient { - static class MockCommand extends Command { - MockCommand(String name, int arg, String key, Object val) { - super(name); - addArg(arg); - addKwArg(key, val); + static class MockCommand extends CustomIntCommand { + MockCommand(int arg, Object val) { + super("foo", arg); + addKwArg("bar", val); } } @@ -237,8 +236,7 @@ void testCall() throws Exception { "return": "Woo" } """); - assertEquals("\"Woo\"", - c.call(new MockCommand("foo", 1, "bar", 2), null)); + assertEquals("\"Woo\"", c.call(new MockCommand(1, 2), null)); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); /* @@ -260,8 +258,7 @@ void testCall() throws Exception { "return": "Woo" } """); - assertEquals("\"Woo\"", - c.call(new MockCommand("foo", 1, "bar", 2), null)); + assertEquals("\"Woo\"", c.call(new MockCommand(1, 2), null)); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); assertEquals(new JobsChangedNotification(1), c.waitForNotification(-1)); @@ -273,7 +270,7 @@ void testCall() throws Exception { // Should be able to timeout immediately long before = System.currentTimeMillis(); assertThrows(SpallocProtocolTimeoutException.class, - () -> c.call(new MockCommand("foo", 1, "bar", 2), TIMEOUT)); + () -> c.call(new MockCommand(1, 2), TIMEOUT)); long after = System.currentTimeMillis(); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); assertTimeout(before, after); @@ -286,7 +283,7 @@ void testCall() throws Exception { """); before = System.currentTimeMillis(); assertThrows(SpallocProtocolTimeoutException.class, - () -> c.call(new MockCommand("foo", 1, "bar", 2), TIMEOUT)); + () -> c.call(new MockCommand(1, 2), TIMEOUT)); after = System.currentTimeMillis(); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); assertTimeout(before, after); @@ -297,7 +294,7 @@ void testCall() throws Exception { // Exceptions should transfer s.send("{\"exception\": \"something informative\"}"); var t = assertThrows(SpallocServerException.class, - () -> c.call(new MockCommand("foo", 1, "bar", 2), TIMEOUT)); + () -> c.call(new MockCommand(1, 2), TIMEOUT)); assertEquals("something informative", t.getMessage()); }); } @@ -331,7 +328,7 @@ void testWaitForNotification() throws Exception { """); s.send("{\"return\": \"Woo\"}"); assertEquals("\"Woo\"", - c.call(new MockCommand("foo", 1, "bar", 2), null)); + c.call(new MockCommand(1, 2), null)); JSONAssert.assertEquals(MOCK_RECEIVED_MESSAGE, s.recv(), true); assertEquals(new JobsChangedNotification(1), c.waitForNotification()); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java index ee503320c9..cb76a0aa40 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java @@ -78,8 +78,9 @@ * @author Donal Fellows * @author Alan Stokes */ -public abstract class DataGatherer extends BoardLocalSupport - implements AutoCloseable { +@SuppressWarnings("deprecation") +public abstract sealed class DataGatherer extends BoardLocalSupport implements + AutoCloseable permits DirectDataGatherer, RecordingRegionDataGatherer { /** * Logger for the gatherer. */ diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java index ee0225d585..166ecb0b38 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DirectDataGatherer.java @@ -50,7 +50,7 @@ * @see RecordingRegionDataGatherer */ @Deprecated -public class DirectDataGatherer extends DataGatherer { +public final class DirectDataGatherer extends DataGatherer { /** The number of memory regions in the DSE model. */ private static final int MAX_MEM_REGIONS = 16; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegionDataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegionDataGatherer.java index a6056d3ae8..05697134e6 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegionDataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/RecordingRegionDataGatherer.java @@ -52,7 +52,7 @@ * * @author Donal Fellows */ -public class RecordingRegionDataGatherer extends DataGatherer { +public final class RecordingRegionDataGatherer extends DataGatherer { /** * How long a termination delay has to be to be worth reporting, in * milliseconds. diff --git a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestReplacer.java b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestReplacer.java index 13d7be1148..e569026138 100644 --- a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestReplacer.java +++ b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/iobuf/TestReplacer.java @@ -34,6 +34,8 @@ public void replace() { replacer.replace("1\u001e2\u001e3\u001e4")); assertEquals("abc,d,1,e,3,f,4", replacer.replace("2\u001e1\u001e3\u001e4")); + assertEquals("abc,d,12345,e,34567,f,45678", + replacer.replace("2\u001e12345\u001e34567\u001e45678")); assertEquals("1,2,3,4", replacer.replace("1,2,3,4")); } } From 95d082e8277960e99b796f887cc19d269874b01c Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 14 Dec 2022 16:53:47 +0000 Subject: [PATCH 026/194] More cleaning up --- .../connections/NotificationConnection.java | 3 +- .../AbstractNotificationMessage.java | 85 ------------------- .../notification/DatabaseConfirmation.java | 2 +- .../notification/NotificationMessage.java | 64 +++++++++++++- .../messages/notification/PauseStop.java | 2 +- .../messages/notification/StartResume.java | 2 +- .../spinnaker/messages/scp/NoResponse.java | 2 +- .../spinnaker/data_spec/Executor.java | 21 +++-- .../spinnaker/py2json/PythonUtils.java | 45 +++------- .../py2json/WithCurrentDirectory.java | 37 ++++---- .../storage/BufferManagerDatabaseEngine.java | 2 +- .../storage/BufferManagerStorage.java | 2 +- .../spinnaker/storage/DSEDatabaseEngine.java | 2 +- .../spinnaker/storage/DSEStorage.java | 2 +- .../spinnaker/storage/DatabaseAPI.java | 2 +- .../spinnaker/storage/DatabaseEngine.java | 5 +- .../storage/sqlite/SQLiteBufferStorage.java | 2 +- .../storage/sqlite/SQLiteDataSpecStorage.java | 4 +- 18 files changed, 125 insertions(+), 159 deletions(-) delete mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/AbstractNotificationMessage.java 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 fc4f02cf83..c30a201ce5 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 @@ -24,7 +24,6 @@ import java.net.InetAddress; import java.nio.ByteBuffer; -import uk.ac.manchester.spinnaker.messages.notification.AbstractNotificationMessage; import uk.ac.manchester.spinnaker.messages.notification.NotificationMessage; /** @@ -123,6 +122,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/messages/notification/AbstractNotificationMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/AbstractNotificationMessage.java deleted file mode 100644 index bdb5975fb0..0000000000 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/AbstractNotificationMessage.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2022 The University of Manchester - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package uk.ac.manchester.spinnaker.messages.notification; - -import java.nio.ByteBuffer; - -import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; - -/** - * An notification message. - * - * @author Donal Fellows - */ -public abstract class AbstractNotificationMessage - implements NotificationMessage { - // Must be power of 2 (minus 1) - private static final int MAX_COMMAND = 0x3FFF; - - private static final int FLAG1_BIT = 15; - - private static final int FLAG2_BIT = 14; - - /** The command code of the message. */ - private final NotificationMessageCode command; - - /** - * @param buffer - * Where to read the command code from. The command code will be - * in the first two bytes; this constructor advances the buffer - * position. - */ - protected AbstractNotificationMessage(ByteBuffer buffer) { - command = NotificationMessageCode.get(buffer.getShort() & MAX_COMMAND); - } - - /** @param command The command code of the message. */ - public AbstractNotificationMessage(NotificationMessageCode command) { - this.command = command; - } - - @Override - @OverridingMethodsMustInvokeSuper - public void addToBuffer(ByteBuffer buffer) { - short value = (short) (0 << FLAG1_BIT | 1 << FLAG2_BIT - | command.getValue()); - buffer.putShort(value); - } - - /** - * Create a notification message instance from a buffer holding a received - * message. - * - * @param buffer - * The received message data buffer. - * @return The parsed message. - * @throws UnsupportedOperationException - * If the message is not understood. - */ - public static NotificationMessage build(ByteBuffer buffer) { - switch (NotificationMessageCode.get(buffer.getShort(0) & MAX_COMMAND)) { - case DATABASE_CONFIRMATION: - return new DatabaseConfirmation(buffer); - case START_RESUME_NOTIFICATION: - return new StartResume(buffer); - case STOP_PAUSE_NOTIFICATION: - return new PauseStop(buffer); - default: - throw new UnsupportedOperationException(); - } - } -} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/DatabaseConfirmation.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/DatabaseConfirmation.java index 7ad4b0193c..82d881413d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/DatabaseConfirmation.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/DatabaseConfirmation.java @@ -27,7 +27,7 @@ * Packet which contains the path to the database created by the toolchain which * is to be used by any software which interfaces with SpiNNaker. */ -public class DatabaseConfirmation extends AbstractNotificationMessage { +public final class DatabaseConfirmation extends NotificationMessage { /** * The path to the database. Note that there is a length limit; the overall * message must fit in a SpiNNaker UDP message. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java index f0a6c9c56b..8f42b830c2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java @@ -16,10 +16,72 @@ */ package uk.ac.manchester.spinnaker.messages.notification; +import java.nio.ByteBuffer; + +import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; + import uk.ac.manchester.spinnaker.messages.SerializableMessage; /** * A notification message. + * + * @author Donal Fellows */ -public interface NotificationMessage extends SerializableMessage { +public abstract sealed class NotificationMessage implements SerializableMessage + permits DatabaseConfirmation, PauseStop, StartResume { + // Must be power of 2 (minus 1) + private static final int MAX_COMMAND = 0x3FFF; + + private static final int FLAG1_BIT = 15; + + private static final int FLAG2_BIT = 14; + + /** The command code of the message. */ + private final NotificationMessageCode command; + + /** + * @param buffer + * Where to read the command code from. The command code will be + * in the first two bytes; this constructor advances the buffer + * position. + */ + protected NotificationMessage(ByteBuffer buffer) { + command = NotificationMessageCode.get(buffer.getShort() & MAX_COMMAND); + } + + /** @param command The command code of the message. */ + public NotificationMessage(NotificationMessageCode command) { + this.command = command; + } + + @Override + @OverridingMethodsMustInvokeSuper + public void addToBuffer(ByteBuffer buffer) { + short value = (short) (0 << FLAG1_BIT | 1 << FLAG2_BIT + | command.getValue()); + buffer.putShort(value); + } + + /** + * Create a notification message instance from a buffer holding a received + * message. + * + * @param buffer + * The received message data buffer. + * @return The parsed message. + * @throws UnsupportedOperationException + * If the message is not understood. + */ + public static NotificationMessage build(ByteBuffer buffer) { + switch (NotificationMessageCode.get(buffer.getShort(0) & MAX_COMMAND)) { + case DATABASE_CONFIRMATION: + return new DatabaseConfirmation(buffer); + case START_RESUME_NOTIFICATION: + return new StartResume(buffer); + case STOP_PAUSE_NOTIFICATION: + return new PauseStop(buffer); + default: + throw new UnsupportedOperationException(); + } + } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/PauseStop.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/PauseStop.java index 553abf8039..e43f752e84 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/PauseStop.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/PauseStop.java @@ -23,7 +23,7 @@ /** * Packet which indicates that the toolchain has paused or stopped. */ -public class PauseStop extends AbstractNotificationMessage { +public final class PauseStop extends NotificationMessage { /** Create an instance. */ public PauseStop() { super(STOP_PAUSE_NOTIFICATION); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/StartResume.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/StartResume.java index f660492d46..ebee2610f7 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/StartResume.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/StartResume.java @@ -23,7 +23,7 @@ /** * Packet which indicates that the toolchain has started or resumed. */ -public class StartResume extends AbstractNotificationMessage { +public final class StartResume extends NotificationMessage { /** Create an instance. */ public StartResume() { super(START_RESUME_NOTIFICATION); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/NoResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/NoResponse.java index 0865a34673..41960fa887 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/NoResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/NoResponse.java @@ -24,7 +24,7 @@ * An SCP response that should never be received because its request is * guaranteed to be a one-way request. */ -public class NoResponse extends SCPResponse { +public final class NoResponse extends SCPResponse { /** * Create an instance. * diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java index efa7b5b5a0..d1ee150bfe 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Executor.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.Collection; import org.slf4j.Logger; @@ -204,6 +205,14 @@ public void addHeader(ByteBuffer buffer) { buffer.putInt(DSE_VERSION); } + private static int checksum(int nWords, IntBuffer buf) { + long sum = 0L; + for (int i = 0; i < nWords; i++) { + sum = (sum + (buf.get() & UNSIGNED_INT)) & UNSIGNED_INT; + } + return (int) (sum & UNSIGNED_INT); + } + /** * Get the pointer table stored in a buffer. * @@ -219,14 +228,12 @@ public void addPointerTable(ByteBuffer buffer) { // Work out the checksum int nWords = ceildiv(regReal.getMaxWritePointer(), INT_SIZE); - var buf = regReal.getRegionData().duplicate() - .order(LITTLE_ENDIAN).rewind().asIntBuffer(); - long sum = 0; - for (int i = 0; i < nWords; i++) { - sum = (sum + (buf.get() & UNSIGNED_INT)) & UNSIGNED_INT; - } + var ck = checksum(nWords, + regReal.getRegionData().duplicate() + .order(LITTLE_ENDIAN).rewind() + .asIntBuffer()); // Write the checksum and number of words - buffer.putInt((int) (sum & UNSIGNED_INT)); + buffer.putInt(ck); buffer.putInt(nWords); } else { // Don't checksum references diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/PythonUtils.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/PythonUtils.java index 1493a8e825..9b9c1f3eff 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/PythonUtils.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/PythonUtils.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -91,26 +92,6 @@ public static PyObject item(PyObject object, PyObject key) { return object.__getitem__(key); } - /** - * An operation used to convert a Python object into something more - * Java-like. - * - * @param - * The type of value to produce. - * @author Donal Fellows - */ - @FunctionalInterface - public interface Depythonizer { - /** - * Convert an object into a Java value. - * - * @param object - * The value to convert. - * @return The value to produce. - */ - T act(PyObject object); - } - /** * Convert an iterable object into a stream. * @@ -143,10 +124,10 @@ private static Stream stream(PyObject iterable) { * @return The map of collections. */ public static , T, U> Map toCollectingMap( - PyObject mapObject, Depythonizer makeKey, - Supplier makeCollector, Depythonizer makeValue) { - return stream(mapObject).collect(groupingBy(makeKey::act, - mapping(makeValue::act, toCollection(makeCollector)))); + PyObject mapObject, Function makeKey, + Supplier makeCollector, Function makeValue) { + return stream(mapObject).collect(groupingBy(makeKey, + mapping(makeValue, toCollection(makeCollector)))); } /** @@ -165,9 +146,9 @@ public static , T, U> Map toCollectingMap( * @return The map. */ public static Map toMap(PyObject dictObject, - Depythonizer makeKey, Depythonizer makeValue) { - return stream(dictObject).collect(Collectors.toMap(makeKey::act, - key -> makeValue.act(item(dictObject, key)))); + Function makeKey, Function makeValue) { + return stream(dictObject).collect(Collectors.toMap(makeKey, + key -> makeValue.apply(item(dictObject, key)))); } /** @@ -182,9 +163,8 @@ public static Map toMap(PyObject dictObject, * @return The list. */ public static List toList(PyObject listObject, - Depythonizer makeValue) { - return stream(listObject).map(makeValue::act) - .collect(Collectors.toList()); + Function makeValue) { + return stream(listObject).map(makeValue).collect(Collectors.toList()); } /** @@ -199,8 +179,7 @@ public static List toList(PyObject listObject, * @return The set. */ public static Set toSet(PyObject listObject, - Depythonizer makeValue) { - return stream(listObject).map(makeValue::act) - .collect(Collectors.toSet()); + Function makeValue) { + return stream(listObject).map(makeValue).collect(Collectors.toSet()); } } diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java index ed09f66841..35a3699628 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java @@ -16,41 +16,44 @@ */ package uk.ac.manchester.spinnaker.py2json; -import static java.lang.String.format; import static java.lang.System.getProperty; +import java.nio.file.Paths; + +import org.python.core.PySystemState; import org.python.util.PythonInterpreter; import com.google.errorprone.annotations.MustBeClosed; /** - * Hack for Java 11 and later, where just changing {@code user.dir} is no longer - * enough. We force the change inside Jython as that's the environment that - * cares. Outside... we shouldn't need to care. + * Sets the Jython notion of what the working directory is for the duration of + * the the context. This isn't properly the current working directory (Java code + * really doesn't care!) but it is what the Python side expects. + *

+ * @see PySystemState#setCurrentWorkingDir(String) */ final class WithCurrentDirectory implements AutoCloseable { - private final PythonInterpreter python; + private final PySystemState sys; + + private final String oldCwd; @MustBeClosed WithCurrentDirectory(PythonInterpreter python, boolean doCd) { - var cwd = getProperty("user.dir"); if (doCd) { - this.python = python; + sys = python.getSystemState(); + oldCwd = sys.getCurrentWorkingDir(); + sys.setCurrentWorkingDir(Paths.get(getProperty("user.dir")) + .toAbsolutePath().toString()); } else { - this.python = null; - } - run(format("import os; __saved=os.getcwd(); os.chdir(r'''%s''')", cwd)); - } - - private void run(String script) { - if (python == null) { - return; + sys = null; + oldCwd = null; } - python.exec(script); } @Override public void close() { - run("os.chdir(__saved)"); + if (sys != null) { + sys.setCurrentWorkingDir(oldCwd); + } } } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerDatabaseEngine.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerDatabaseEngine.java index 616dbc5cf5..a80447af58 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerDatabaseEngine.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerDatabaseEngine.java @@ -27,7 +27,7 @@ * * @author Donal Fellows */ -public class BufferManagerDatabaseEngine +public final class BufferManagerDatabaseEngine extends DatabaseEngine { private static String sqlDDL = loadResource("buffer_manager.sql"); diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java index be1c2a1587..06b4e9a32e 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java @@ -33,7 +33,7 @@ * * @author Donal Fellows */ -public interface BufferManagerStorage extends DatabaseAPI { +public non-sealed interface BufferManagerStorage extends DatabaseAPI { /** * Retrieves some bytes from the database. The bytes represent the contents * of a DSE region of a particular SpiNNaker core. diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEDatabaseEngine.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEDatabaseEngine.java index e3d36bf9ef..454e1eff4a 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEDatabaseEngine.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEDatabaseEngine.java @@ -27,7 +27,7 @@ * * @author Donal Fellows */ -public class DSEDatabaseEngine extends DatabaseEngine { +public final class DSEDatabaseEngine extends DatabaseEngine { private static String sqlDDL = loadResource("dse.sql"); /** diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java index 9023542b50..a3a03e7bfa 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java @@ -32,7 +32,7 @@ * * @author Donal Fellows */ -public interface DSEStorage extends DatabaseAPI { +public non-sealed interface DSEStorage extends DatabaseAPI { /** * See how many DSE loading actions have to be done. * diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java index f4a1f019cc..28c5f9ff8f 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java @@ -21,5 +21,5 @@ * * @author Donal Fellows */ -public interface DatabaseAPI { +public sealed interface DatabaseAPI permits BufferManagerStorage, DSEStorage { } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java index f5d8ef7a41..b9fc7fc2bc 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java @@ -38,8 +38,9 @@ * The type of the higher-level access interface that can be used to * work with the database this class makes connections to. */ -public abstract class DatabaseEngine - implements ConnectionProvider { +public abstract sealed class DatabaseEngine + implements ConnectionProvider + permits BufferManagerDatabaseEngine, DSEDatabaseEngine { private static final Logger log = getLogger(DatabaseEngine.class); /** Busy timeout for SQLite, in milliseconds. */ diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java index 991e1588a7..fca01bfc74 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java @@ -59,7 +59,7 @@ * * @author Donal Fellows */ -public class SQLiteBufferStorage +public final class SQLiteBufferStorage extends SQLiteConnectionManager implements BufferManagerStorage { private static final Logger log = getLogger(SQLiteBufferStorage.class); diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index e4781757e2..2fb72ba1ae 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -46,8 +46,8 @@ * * @author Donal Fellows */ -public class SQLiteDataSpecStorage extends SQLiteConnectionManager - implements DSEStorage { +public final class SQLiteDataSpecStorage + extends SQLiteConnectionManager implements DSEStorage { /** * Create an instance. * From 69766db643c1c7851b53f1ad113bff672a7dd5e1 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 16 Dec 2022 16:29:32 +0000 Subject: [PATCH 027/194] Convert ProxyInformation to a record --- .../alloc/client/SpallocClientFactory.java | 4 +- .../spinnaker/storage/ProxyInformation.java | 44 ++++--------------- 2 files changed, 11 insertions(+), 37 deletions(-) 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 5c325766cb..fa0a0996ce 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 @@ -144,8 +144,8 @@ public static Job getJobFromProxyInfo(ProxyInformation proxy) if (proxy == null) { return null; } - return new SpallocClientFactory(URI.create(proxy.spallocUrl)) - .getJob(proxy.jobUrl, proxy.bearerToken); + return new SpallocClientFactory(URI.create(proxy.spallocUrl())) + .getJob(proxy.jobUrl(), proxy.bearerToken()); } /** diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java index 7b33787a99..20389f6bcd 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java @@ -20,40 +20,14 @@ /** * Information about the proxy to allow connection. + * + * @param spallocUrl + * The URL of the spalloc server to connect to. + * @param jobUrl + * The URL of the job to connect to. + * @param bearerToken + * The bearer token to use as authentication. */ -public class ProxyInformation { - /** - * The URL of the spalloc server to connect to. - */ - @NotEmpty - public final String spallocUrl; - - /** - * The URL of the job to connect to. - */ - @NotEmpty - public final String jobUrl; - - /** - * The token to use to authenticate access. - */ - @NotEmpty - public final String bearerToken; - - /** - * Create a new instance. - * - * @param spallocUrl - * The URL of the Spalloc server. - * @param jobUrl - * The URL of the job. - * @param bearerToken - * The bearer token to use as authentication. - */ - public ProxyInformation(String spallocUrl, String jobUrl, - String bearerToken) { - this.spallocUrl = spallocUrl; - this.jobUrl = jobUrl; - this.bearerToken = bearerToken; - } +public record ProxyInformation(@NotEmpty String spallocUrl, + @NotEmpty String jobUrl, @NotEmpty String bearerToken) { } From c4d951d36984816814938b0bba4bfe25133cd27a Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 16 Dec 2022 16:30:28 +0000 Subject: [PATCH 028/194] Missed a spot --- .../spinnaker/front_end/dse/ExecuteDataSpecification.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java index 001c6f5c86..77edf85f77 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java @@ -105,7 +105,7 @@ protected ExecuteDataSpecification(Machine machine, DSEDatabaseEngine db) txrx = new Transceiver(machine); } else { log.debug("Getting transceiver via proxy on {}", - proxy.spallocUrl); + proxy.spallocUrl()); job = SpallocClientFactory.getJobFromProxyInfo(proxy); txrx = job.getTransceiver(); } From 090a49e90ab5369df3ef865e1a8cc756d9e20023 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 16 Dec 2022 16:56:00 +0000 Subject: [PATCH 029/194] Mark some classes as final --- .../uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java index 584c66971d..d281605da6 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java @@ -826,7 +826,7 @@ private StackTraceCaptureException() { * {@link ConnectionImpl}. {@link #stateMap} is responsible for issuing the * correct one for a connection. */ - private static class ConnectionState { + private static final class ConnectionState { private boolean inTransaction; private boolean isLockedForWrites; @@ -892,7 +892,7 @@ public boolean isHistoricalDBAvailable() { return state.canTombstone; } - private class Locker implements AutoCloseable { + private final class Locker implements AutoCloseable { private final long lockTimestamp; private final Object lockingContext; From e229358065a8bfa53cc98c216acb60a030cf2adc Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 16 Dec 2022 17:31:56 +0000 Subject: [PATCH 030/194] Tidy up --- .../messages/eieio/EIEIOMessageFactory.java | 50 ++++----- .../transceiver/ProcessException.java | 4 +- .../spinnaker/transceiver/Transceiver.java | 6 +- .../spinnaker/front_end/DebuggingUtils.java | 100 ++++++++++++++++++ .../front_end/download/DataGatherer.java | 62 ++--------- .../dse/FastExecuteDataSpecification.java | 54 +--------- .../datalinks/TestAbstractDataLink.java | 3 +- .../storage/sqlite/SQLiteDataSpecStorage.java | 6 +- 8 files changed, 136 insertions(+), 149 deletions(-) create mode 100644 SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageFactory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageFactory.java index 14f62edc73..70635dab14 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageFactory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessageFactory.java @@ -41,37 +41,29 @@ private EIEIOMessageFactory() { */ public static EIEIOCommandMessage readCommandMessage(ByteBuffer data) { var command = peekCommand(data); - if (!(command instanceof EIEIOCommandID)) { - return new EIEIOCommandMessage(data); - } - switch ((EIEIOCommandID) command) { - case EVENT_PADDING: - // Fill in buffer area with padding - return new PaddingRequest(); - case EVENT_STOP: - // End of all buffers, stop execution - return new EventStopRequest(); - case STOP_SENDING_REQUESTS: - // Stop complaining that there is SDRAM free space for buffers - return new StopRequests(); - case START_SENDING_REQUESTS: - // Start complaining that there is SDRAM free space for buffers - return new StartRequests(); - case SPINNAKER_REQUEST_BUFFERS: - // SpiNNaker requesting new buffers for spike source population - return new SpinnakerRequestBuffers(data); - case HOST_SEND_SEQUENCED_DATA: - // Buffers being sent from host to SpiNNaker - return new HostSendSequencedData(data); - case SPINNAKER_REQUEST_READ_DATA: - // Buffers available to be read from a buffered out vertex - return new SpinnakerRequestReadData(data); - case HOST_DATA_READ: - // Host confirming data being read form SpiNNaker memory - return new HostDataRead(data); - default: + if (!(command instanceof EIEIOCommandID cmd)) { return new EIEIOCommandMessage(data); } + return switch (cmd) { + // Fill in buffer area with padding + case EVENT_PADDING -> new PaddingRequest(); + // End of all buffers, stop execution + case EVENT_STOP -> new EventStopRequest(); + // Stop complaining that there is SDRAM free space for buffers + case STOP_SENDING_REQUESTS -> new StopRequests(); + // Start complaining that there is SDRAM free space for buffers + case START_SENDING_REQUESTS -> new StartRequests(); + // SpiNNaker requesting new buffers for spike source population + case SPINNAKER_REQUEST_BUFFERS -> new SpinnakerRequestBuffers(data); + // Buffers being sent from host to SpiNNaker + case HOST_SEND_SEQUENCED_DATA -> new HostSendSequencedData(data); + // Buffers available to be read from a buffered out vertex + case SPINNAKER_REQUEST_READ_DATA -> new SpinnakerRequestReadData(data); + // Host confirming data being read form SpiNNaker memory + case HOST_DATA_READ -> new HostDataRead(data); + // Some non-standard message + default -> new EIEIOCommandMessage(data); + }; } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java index 177315c19c..04d4216cbc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java @@ -111,8 +111,8 @@ static ProcessException makeInstance(HasCoreLocation core, // Fall through } } - if (cause instanceof InterruptedException) { - throw (InterruptedException) cause; + if (cause instanceof InterruptedException interrupt) { + throw interrupt; } return new ProcessException(core, cause, null); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 8da25f4894..70fe8672da 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -1154,9 +1154,9 @@ private TxrxProcess simpleProcess(SDPConnection connector) throws IOException { // Avoid delegation of the connection if not needed - if (connector instanceof SCPConnection) { - return new TxrxProcess(new SingletonConnectionSelector<>( - (SCPConnection) connector), this); + if (connector instanceof SCPConnection scpConn) { + return new TxrxProcess(new SingletonConnectionSelector<>(scpConn), + this); } return new TxrxProcess(new SingletonConnectionSelector<>( new DelegatingSCPConnection(connector)), this); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java new file mode 100644 index 0000000000..977ff550b7 --- /dev/null +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019-2022 The University of Manchester + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package uk.ac.manchester.spinnaker.front_end; + +import static difflib.DiffUtils.diff; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; +import static java.util.stream.Collectors.toList; + +import java.nio.ByteBuffer; +import java.util.List; + +import org.slf4j.Logger; + +import difflib.Chunk; +import uk.ac.manchester.spinnaker.utils.MathUtils; + +/** + * Utilities for debugging. + */ +public abstract class DebuggingUtils { + private DebuggingUtils() { + } + + /** + * Compare two buffers and write a description of how they differ to the + * given log (if they actually differ). + * + * @param original + * The data to compare against. The ground truth. + * @param downloaded + * The data that is being checked for differences. + * @param log + * Where to write messages on differences being found. + */ + public static void compareBuffers(ByteBuffer original, + ByteBuffer downloaded, Logger log) { + for (int i = 0; i < original.remaining(); i++) { + if (original.get(i) != downloaded.get(i)) { + log.error("downloaded buffer contents different"); + for (var delta : diff(list(original), list(downloaded)) + .getDeltas()) { + switch (delta.getType()) { + case CHANGE: + var changeFrom = delta.getOriginal(); + var changeTo = delta.getRevised(); + log.warn( + "swapped {} bytes (SCP) for {} (gather) " + + "at {}->{}", + changeFrom.getLines().size(), + changeTo.getLines().size(), + changeFrom.getPosition(), + changeTo.getPosition()); + log.info("change {} -> {}", describeChunk(changeFrom), + describeChunk(changeTo)); + break; + case DELETE: + var delete = delta.getOriginal(); + log.warn("gather deleted {} bytes at {}", + delete.getLines().size(), delete.getPosition()); + log.info("delete {}", describeChunk(delete)); + break; + case INSERT: + var insert = delta.getRevised(); + log.warn("gather inserted {} bytes at {}", + insert.getLines().size(), insert.getPosition()); + log.info("insert {}", describeChunk(insert)); + break; + default: + // Should be unreachable + break; + } + } + break; + } + } + } + + private static List list(ByteBuffer buffer) { + return sliceUp(buffer, 1).map(ByteBuffer::get).toList(); + } + + private static List describeChunk(Chunk chunk) { + return chunk.getLines().stream().map(MathUtils::hexbyte) + .collect(toList()); + } +} diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java index d963071e55..ad5be3fdb5 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/DataGatherer.java @@ -16,19 +16,17 @@ */ package uk.ac.manchester.spinnaker.front_end.download; -import static difflib.DiffUtils.diff; import static java.lang.String.format; import static java.lang.System.getProperty; import static java.lang.Thread.sleep; import static java.nio.ByteBuffer.allocate; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toUnmodifiableList; import static org.slf4j.LoggerFactory.getLogger; import static uk.ac.manchester.spinnaker.front_end.Constants.PARALLEL_SIZE; +import static uk.ac.manchester.spinnaker.front_end.DebuggingUtils.compareBuffers; import static uk.ac.manchester.spinnaker.front_end.download.MissingSequenceNumbersMessage.createMessages; import static uk.ac.manchester.spinnaker.messages.Constants.SDP_PAYLOAD_WORDS; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.io.IOException; @@ -46,13 +44,8 @@ import com.google.errorprone.annotations.MustBeClosed; import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; -import difflib.ChangeDelta; -import difflib.Chunk; -import difflib.DeleteDelta; -import difflib.InsertDelta; import uk.ac.manchester.spinnaker.alloc.client.SpallocClient; import uk.ac.manchester.spinnaker.connections.MostDirectConnectionSelector; -import uk.ac.manchester.spinnaker.connections.SCPConnection; import uk.ac.manchester.spinnaker.front_end.BasicExecutor; import uk.ac.manchester.spinnaker.front_end.BasicExecutor.SimpleCallable; import uk.ac.manchester.spinnaker.front_end.BoardLocalSupport; @@ -69,7 +62,6 @@ import uk.ac.manchester.spinnaker.storage.StorageException; import uk.ac.manchester.spinnaker.transceiver.ProcessException; import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; -import uk.ac.manchester.spinnaker.utils.MathUtils; import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; import uk.ac.manchester.spinnaker.utils.ValueHolder; @@ -338,14 +330,10 @@ private Map createConnections( if (!work.containsKey(gathererChip)) { continue; } - SCPConnection scp = null; - if (job != null) { - scp = job.getConnection(gathererChip); - } else { - scp = txrx.locateSpinnakerConnection( - g.getIptag().getBoardAddress()); - } - var conn = new GatherDownloadConnection(scp); + var conn = new GatherDownloadConnection( + (job != null) ? job.getConnection(gathererChip) + : txrx.locateSpinnakerConnection( + g.getIptag().getBoardAddress())); conn.setIPTag(txrx, g.getIptag()); connections.put(gathererChip, conn); } @@ -452,45 +440,7 @@ private void compareDownloadWithSCP(Region r, ByteBuffer data) log.error("different buffer sizes: {} with gatherer, {} with SCP", data.remaining(), data2.remaining()); } - for (int i = 0; i < data.remaining(); i++) { - if (data.get(i) != data2.get(i)) { - log.error("downloaded buffer contents different"); - for (var delta : diff(list(data2), list(data)).getDeltas()) { - if (delta instanceof ChangeDelta) { - var delete = delta.getOriginal(); - var insert = delta.getRevised(); - log.warn( - "swapped {} bytes (SCP) for {} (gather) " - + "at {}->{}", - delete.getLines().size(), - insert.getLines().size(), delete.getPosition(), - insert.getPosition()); - log.info("change {} -> {}", describeChunk(delete), - describeChunk(insert)); - } else if (delta instanceof DeleteDelta) { - var delete = delta.getOriginal(); - log.warn("gather deleted {} bytes at {}", - delete.getLines().size(), delete.getPosition()); - log.info("delete {}", describeChunk(delete)); - } else if (delta instanceof InsertDelta) { - var insert = delta.getRevised(); - log.warn("gather inserted {} bytes at {}", - insert.getLines().size(), insert.getPosition()); - log.info("insert {}", describeChunk(insert)); - } - } - break; - } - } - } - - private static List list(ByteBuffer buffer) { - return sliceUp(buffer, 1).map(ByteBuffer::get).toList(); - } - - private static List describeChunk(Chunk chunk) { - return chunk.getLines().stream().map(MathUtils::hexbyte) - .collect(toList()); + compareBuffers(data, data2, log); } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index c0642660b1..02504d00ad 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -16,7 +16,6 @@ */ package uk.ac.manchester.spinnaker.front_end.dse; -import static difflib.DiffUtils.diff; import static java.lang.Integer.toUnsignedLong; import static java.lang.String.format; import static java.lang.System.getProperty; @@ -28,9 +27,9 @@ import static org.slf4j.LoggerFactory.getLogger; import static uk.ac.manchester.spinnaker.data_spec.Constants.APP_PTR_TABLE_BYTE_SIZE; import static uk.ac.manchester.spinnaker.front_end.Constants.CORE_DATA_SDRAM_BASE_TAG; +import static uk.ac.manchester.spinnaker.front_end.DebuggingUtils.compareBuffers; import static uk.ac.manchester.spinnaker.front_end.dse.FastDataInProtocol.computeNumPackets; import static uk.ac.manchester.spinnaker.messages.Constants.NBBY; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; import static uk.ac.manchester.spinnaker.utils.UnitConstants.NSEC_PER_SEC; import java.io.BufferedWriter; @@ -54,10 +53,6 @@ import com.google.errorprone.annotations.CheckReturnValue; import com.google.errorprone.annotations.MustBeClosed; -import difflib.ChangeDelta; -import difflib.Chunk; -import difflib.DeleteDelta; -import difflib.InsertDelta; import uk.ac.manchester.spinnaker.data_spec.DataSpecificationException; import uk.ac.manchester.spinnaker.data_spec.Executor; import uk.ac.manchester.spinnaker.data_spec.MemoryRegion; @@ -79,7 +74,6 @@ import uk.ac.manchester.spinnaker.storage.DSEStorage.Ethernet; import uk.ac.manchester.spinnaker.storage.StorageException; import uk.ac.manchester.spinnaker.transceiver.ProcessException; -import uk.ac.manchester.spinnaker.utils.MathUtils; /** * Implementation of the Data Specification Executor that uses the Fast Data In @@ -331,50 +325,6 @@ baseAddress, toUnsignedLong(size), timeTaken, mbs, } } - private static void compareBuffers(ByteBuffer original, - ByteBuffer downloaded) { - for (int i = 0; i < original.remaining(); i++) { - if (original.get(i) != downloaded.get(i)) { - log.error("downloaded buffer contents different"); - for (var delta : diff(list(original), list(downloaded)) - .getDeltas()) { - if (delta instanceof ChangeDelta) { - var delete = delta.getOriginal(); - var insert = delta.getRevised(); - log.warn( - "swapped {} bytes (SCP) for {} (gather) " - + "at {}->{}", - delete.getLines().size(), - insert.getLines().size(), delete.getPosition(), - insert.getPosition()); - log.info("change {} -> {}", describeChunk(delete), - describeChunk(insert)); - } else if (delta instanceof DeleteDelta) { - var delete = delta.getOriginal(); - log.warn("gather deleted {} bytes at {}", - delete.getLines().size(), delete.getPosition()); - log.info("delete {}", describeChunk(delete)); - } else if (delta instanceof InsertDelta) { - var insert = delta.getRevised(); - log.warn("gather inserted {} bytes at {}", - insert.getLines().size(), insert.getPosition()); - log.info("insert {}", describeChunk(insert)); - } - } - break; - } - } - } - - private static List list(ByteBuffer buffer) { - return sliceUp(buffer, 1).map(ByteBuffer::get).toList(); - } - - private static List describeChunk(Chunk chunk) { - return chunk.getLines().stream().map(MathUtils::hexbyte) - .collect(toList()); - } - /** * The worker class that handles a particular board of a SpiNNaker machine. * Instances of this class are only ever used from a single thread. @@ -503,7 +453,7 @@ private int loadCoreFromExecutor(CoreToLoad ctl, Gather gather, if (SPINNAKER_COMPARE_UPLOAD != null) { var readBack = txrx.readMemory(ctl.core, r.getRegionBase(), r.getRegionData().remaining()); - compareBuffers(r.getRegionData(), readBack); + compareBuffers(r.getRegionData(), readBack, log); } } diff --git a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/datalinks/TestAbstractDataLink.java b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/datalinks/TestAbstractDataLink.java index 138de01849..0429b6cee1 100644 --- a/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/datalinks/TestAbstractDataLink.java +++ b/SpiNNaker-machine/src/test/java/uk/ac/manchester/spinnaker/machine/datalinks/TestAbstractDataLink.java @@ -63,8 +63,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return (obj instanceof AbstractDataLink) - && sameAs((AbstractDataLink) obj); + return (obj instanceof AbstractDataLink link) && sameAs(link); } } } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index 0b35d5780c..ab4b8b96bc 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -227,11 +227,7 @@ private EthernetImpl(int id, int etherx, int ethery, String addr) { @Override public boolean equals(Object other) { - if (!(other instanceof EthernetImpl)) { - return false; - } - var b = (EthernetImpl) other; - return id == b.id; + return (other instanceof EthernetImpl b) && id == b.id; } @Override From e86d333d02f42059c9c48c22b5d9525f77eb3159 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 09:46:45 +0000 Subject: [PATCH 031/194] Bump cxf.version from 3.5.5 to 4.0.0 Bumps `cxf.version` from 3.5.5 to 4.0.0. Updates `cxf-rt-frontend-jaxrs` from 3.5.5 to 4.0.0 Updates `cxf-spring-boot-starter-jaxrs` from 3.5.5 to 4.0.0 Updates `cxf-bom` from 3.5.5 to 4.0.0 --- updated-dependencies: - dependency-name: org.apache.cxf:cxf-rt-frontend-jaxrs dependency-type: direct:production update-type: version-update:semver-major - dependency-name: org.apache.cxf:cxf-spring-boot-starter-jaxrs dependency-type: direct:production update-type: version-update:semver-major - dependency-name: org.apache.cxf:cxf-bom dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1445b76907..e32b392f3b 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ along with this program. If not, see . --> 5.8.1 - 3.5.5 + 4.0.0 2.14.1 2.14 3.40.0.0 From e9b7b27a70fbc936b9f32f8b80942523cee55ff0 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 10:30:09 +0000 Subject: [PATCH 032/194] Corrections --- .../uk/ac/manchester/spinnaker/alloc/SpallocProperties.java | 2 -- .../uk/ac/manchester/spinnaker/alloc/allocator/Epochs.java | 4 ++-- .../uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java index 682ab8fb97..f910afe662 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java @@ -35,7 +35,6 @@ import javax.validation.constraints.PositiveOrZero; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConstructorBinding; import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.core.io.Resource; import org.springframework.validation.annotation.Validated; @@ -52,7 +51,6 @@ * @author Donal Fellows */ @ConfigurationProperties("spalloc") -@ConstructorBinding @Validated public class SpallocProperties { /** Path to the main database file. */ 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 455d0220dc..f0a3076991 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,12 +20,12 @@ import java.time.Duration; -import javax.annotation.PreDestroy; - import org.springframework.stereotype.Service; import com.google.errorprone.annotations.concurrent.GuardedBy; +import jakarta.annotation.PreDestroy; + /** * Manages epoch counters. * diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java index 48c50e3e2e..925f808331 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseEngine.java @@ -1276,7 +1276,7 @@ public Path getDatabasePath() { + "BMPController$AbstractSQL"); private static final Set FILTERED_PREFIXES = Set.of(// - "java", "javax", "sun"); + "java", "javax", "sun", "jakarta"); /** * Get the stack frame description of the caller of the of the transaction. From 4649f4a8528c33789aaee6b38c13581af173be2c Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 11:56:21 +0000 Subject: [PATCH 033/194] Version bumps --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 213031db96..9e903b462c 100644 --- a/pom.xml +++ b/pom.xml @@ -43,8 +43,8 @@ along with this program. If not, see . 2.0.6 2.19.0 - 6.0.0 - 3.0.0 + 6.0.3 + 3.0.1 - 6.0.0 + 6.0.1 4.0.0 2.14.1 From bfa652f5cd9a871e5586419c8846e771df3275d0 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 12:21:32 +0000 Subject: [PATCH 034/194] Change which dependency we use See the otherwise tangentially related FasterXML/jackson-jaxrs-providers#160 for the discussion which informed me what the problem was. The JEE upgrade is a mess. --- SpiNNaker-allocserv/pom.xml | 4 ++-- .../java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SpiNNaker-allocserv/pom.xml b/SpiNNaker-allocserv/pom.xml index 1647e6bb63..a64138e6d3 100644 --- a/SpiNNaker-allocserv/pom.xml +++ b/SpiNNaker-allocserv/pom.xml @@ -366,8 +366,8 @@ along with this program. If not, see . spring-boot-starter-security - com.fasterxml.jackson.jaxrs - jackson-jaxrs-json-provider + com.fasterxml.jackson.jakarta.rs + jackson-jakarta-rs-json-provider org.springframework.boot diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java index abe9e82f3a..e3bd544adf 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java @@ -75,7 +75,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider; import jakarta.ws.rs.ext.Provider; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AllocatorProperties; From aedbf4f6dc5158f7637d7f37ec4464474406c0c7 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 12:35:40 +0000 Subject: [PATCH 035/194] Add missing dependency It was marked optional in the POM of the dependencies that needed it, but the way we use those dependencies makes it not actually optional. Lovely... --- SpiNNaker-allocserv/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SpiNNaker-allocserv/pom.xml b/SpiNNaker-allocserv/pom.xml index a64138e6d3..4457633281 100644 --- a/SpiNNaker-allocserv/pom.xml +++ b/SpiNNaker-allocserv/pom.xml @@ -349,6 +349,11 @@ along with this program. If not, see . org.apache.cxf cxf-rt-frontend-jaxrs + + + jakarta.xml.ws + jakarta.xml.ws-api + org.springframework.boot spring-boot-starter-web From 3dca20b4c3972f85a32e4eea2a7933daa2012615 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 13:08:10 +0000 Subject: [PATCH 036/194] Update to right JSTL URIs --- .../src/main/webapp/WEB-INF/views/admin/board.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/createuser.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/footer.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/groupdetails.jsp | 4 ++-- .../src/main/webapp/WEB-INF/views/admin/listgroups.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/listusers.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/machine.jsp | 2 +- .../src/main/webapp/WEB-INF/views/admin/userdetails.jsp | 4 ++-- .../src/main/webapp/WEB-INF/views/basicfooter.jsp | 2 +- .../src/main/webapp/WEB-INF/views/data/jobdetails_obj.jsp | 2 +- .../src/main/webapp/WEB-INF/views/data/machinedetails_obj.jsp | 2 +- .../src/main/webapp/WEB-INF/views/erroroccurred.jsp | 2 +- SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/head.jsp | 2 +- SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/index.jsp | 2 +- .../src/main/webapp/WEB-INF/views/jobdetails.jsp | 2 +- .../src/main/webapp/WEB-INF/views/listjobs.jsp | 2 +- .../src/main/webapp/WEB-INF/views/listmachines.jsp | 4 ++-- SpiNNaker-allocserv/src/main/webapp/WEB-INF/views/login.jsp | 2 +- .../src/main/webapp/WEB-INF/views/machinedetails.jsp | 4 ++-- .../src/main/webapp/WEB-INF/views/password.jsp | 2 +- 20 files changed, 24 insertions(+), 24 deletions(-) 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 13853d003b..13d4bcd49c 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 f1863c4a12..4a074e41ba 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 0dd1d29ec4..44d0e5c7cf 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 1056132260..d5ac1823fe 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 a7d8a0c54a..f6d9d4704f 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 08c8590e9e..9b66396aff 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 6b425041f7..c89798faee 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 a30686b4db..9f7ddf52d8 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 dce0fe791d..51527df7cf 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 7b2950a970..2de3bf78d6 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 9c59f12e47..a2f7217da0 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 a9a1317331..ece6a83be3 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 b030be3c42..5f4087512c 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 2b9abb5fda..1ffa87a716 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 265c91ae41..83d18db16c 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 a8a49f15d4..c06992a043 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 15bfc9f826..192c4f0d8e 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 421ccdba6d..dd5f9b7c29 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 ee22d3989f..a780a577c7 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 5e37fd6657..09f3da7f31 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"%> <%-- From 085d973094896424b29f41fbef9376d20243041b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 14:42:36 +0000 Subject: [PATCH 037/194] Change to which version of JSPC plugin Something more actively maintained would be nice... --- SpiNNaker-allocserv/pom.xml | 12 +++++++----- pom.xml | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/SpiNNaker-allocserv/pom.xml b/SpiNNaker-allocserv/pom.xml index 4457633281..3d5e075ebb 100644 --- a/SpiNNaker-allocserv/pom.xml +++ b/SpiNNaker-allocserv/pom.xml @@ -251,10 +251,12 @@ along with this program. If not, see . - org.apache.sling + io.leonard.maven.plugins jspc-maven-plugin - ${project.basedir}/src/main/webapp/WEB-INF + + ${project.basedir}/src/main/webapp/WEB-INF/**/*.jsp + @@ -515,14 +517,14 @@ along with this program. If not, see . - org.apache.sling + io.leonard.maven.plugins jspc-maven-plugin + jspc - jspc + compile - compile diff --git a/pom.xml b/pom.xml index 9e903b462c..191deb8e08 100644 --- a/pom.xml +++ b/pom.xml @@ -587,9 +587,9 @@ along with this program. If not, see . 1.0 - org.apache.sling + io.leonard.maven.plugins jspc-maven-plugin - 2.3.4 + 4.0.1 org.apache.rat From fd7232a492b47375e872bece0908b1312404931b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 15:37:37 +0000 Subject: [PATCH 038/194] Validation is also in the new Jakarta hierarchy --- .../spinnaker/alloc/ServiceConfig.java | 19 ++++++++--------- .../spinnaker/alloc/SpallocProperties.java | 21 +++++++++---------- .../spinnaker/alloc/admin/AdminAPI.java | 7 +++---- .../alloc/admin/AdminController.java | 15 +++++++------ .../alloc/admin/MachineDefinitionLoader.java | 15 +++++++------ .../alloc/admin/MachineStateControl.java | 7 +++---- .../spinnaker/alloc/allocator/SpallocAPI.java | 11 +++++----- .../spinnaker/alloc/compat/Command.java | 6 +++--- .../spinnaker/alloc/compat/SaneParameter.java | 8 +++---- .../spinnaker/alloc/compat/V1CompatTask.java | 9 ++++---- .../spinnaker/alloc/model/BoardRecord.java | 5 ++--- .../spinnaker/alloc/model/ConnectionInfo.java | 3 +-- .../spinnaker/alloc/model/DownLink.java | 6 +++--- .../spinnaker/alloc/model/GroupRecord.java | 5 ++--- .../spinnaker/alloc/model/JobDescription.java | 5 ++--- .../alloc/model/JobListEntryRecord.java | 8 +++---- .../alloc/model/MachineDescription.java | 7 +++---- .../alloc/model/MachineListEntryRecord.java | 6 +++--- .../spinnaker/alloc/model/MachineTagging.java | 3 +-- .../spinnaker/alloc/model/MemberRecord.java | 4 ++-- .../alloc/model/PasswordChangeRecord.java | 6 +++--- .../spinnaker/alloc/model/TagList.java | 4 ++-- .../spinnaker/alloc/model/UserRecord.java | 9 ++++---- .../spinnaker/alloc/web/CreateJobRequest.java | 15 +++++++------ .../alloc/web/IssueReportRequest.java | 7 +++---- .../spinnaker/alloc/web/MachinePower.java | 3 +-- .../alloc/web/SpallocServiceAPI.java | 11 +++++----- .../spinnaker/alloc/web/SystemController.java | 3 +-- .../alloc/web/SystemControllerImpl.java | 3 +-- .../spinnaker/alloc/bmp/MockTransceiver.java | 5 ++--- SpiNNaker-comms/pom.xml | 2 +- .../alloc/client/AllocatedMachine.java | 5 ++--- .../spinnaker/alloc/client/CreateJob.java | 9 ++++---- .../spinnaker/alloc/client/SpallocClient.java | 5 ++--- .../messages/model/BMPConnectionData.java | 3 +-- .../spinnaker/messages/model/Blacklist.java | 3 +-- .../messages/model/ExecutableTargets.java | 7 +++---- .../messages/scp/ApplicationRun.java | 3 +-- .../spinnaker/messages/scp/IPTagSet.java | 7 +++---- .../messages/scp/ReverseIPTagSet.java | 5 ++--- .../spinnaker/messages/sdp/SDPHeader.java | 5 ++--- .../spinnaker/spalloc/Configuration.java | 7 +++---- .../spinnaker/spalloc/CreateJob.java | 9 ++++---- .../spinnaker/spalloc/SpallocAPI.java | 11 +++++----- .../spalloc/messages/Connection.java | 3 +-- .../messages/GetBoardAtPositionCommand.java | 5 ++--- .../messages/GetBoardPositionCommand.java | 5 ++--- .../spinnaker/spalloc/messages/JobState.java | 4 ++-- .../WhereIsMachineBoardLogicalCommand.java | 5 ++--- .../WhereIsMachineBoardPhysicalCommand.java | 7 +++---- .../transceiver/BMPTransceiverInterface.java | 7 +++---- .../spinnaker/transceiver/Transceiver.java | 5 ++--- .../transceiver/TransceiverInterface.java | 11 +++++----- .../UnimplementedBMPTransceiver.java | 5 ++--- .../front_end/download/request/Gather.java | 3 +-- .../front_end/download/request/Monitor.java | 5 ++--- .../front_end/download/request/Vertex.java | 8 +++---- .../front_end/iobuf/IobufRequest.java | 7 +++---- SpiNNaker-machine/pom.xml | 2 +- .../ac/manchester/spinnaker/machine/Chip.java | 2 +- .../spinnaker/machine/CoreSubsets.java | 3 +-- .../ac/manchester/spinnaker/machine/Link.java | 4 ++-- .../manchester/spinnaker/machine/Machine.java | 2 +- .../spinnaker/machine/RoutingEntry.java | 2 +- .../spinnaker/machine/ValidMachineHeight.java | 10 ++++----- .../spinnaker/machine/ValidMachineWidth.java | 10 ++++----- .../manchester/spinnaker/machine/ValidP.java | 10 ++++----- .../manchester/spinnaker/machine/ValidX.java | 10 ++++----- .../manchester/spinnaker/machine/ValidY.java | 10 ++++----- .../spinnaker/machine/bean/ChipBean.java | 7 +++---- .../spinnaker/machine/bean/ChipDetails.java | 9 ++++---- .../spinnaker/machine/bean/LinkBean.java | 5 ++--- .../spinnaker/machine/bean/MachineBean.java | 6 +++--- .../machine/board/ValidBoardNumber.java | 8 +++---- .../machine/board/ValidCabinetNumber.java | 8 +++---- .../machine/board/ValidFrameNumber.java | 8 +++---- .../machine/board/ValidTriadDepth.java | 10 ++++----- .../machine/board/ValidTriadHeight.java | 10 ++++----- .../machine/board/ValidTriadWidth.java | 10 ++++----- .../spinnaker/machine/board/ValidTriadX.java | 10 ++++----- .../spinnaker/machine/board/ValidTriadY.java | 10 ++++----- .../spinnaker/machine/board/ValidTriadZ.java | 10 ++++----- .../machine/datalinks/AbstractDataLink.java | 3 +-- .../spinnaker/machine/tags/IPTag.java | 3 +-- .../spinnaker/machine/tags/ReverseIPTag.java | 3 +-- .../spinnaker/machine/tags/Tag.java | 3 +-- .../spinnaker/machine/tags/TagID.java | 8 +++---- .../spinnaker/py2json/Configuration.java | 9 ++++---- .../manchester/spinnaker/py2json/Machine.java | 11 +++++----- .../storage/BufferManagerStorage.java | 9 ++++---- .../spinnaker/storage/DSEStorage.java | 5 ++--- .../spinnaker/storage/ProxyInformation.java | 2 +- .../spinnaker/utils/validation/IPAddress.java | 8 +++---- .../spinnaker/utils/validation/TCPPort.java | 8 +++---- .../spinnaker/utils/validation/UDPPort.java | 8 +++---- pom.xml | 2 +- 96 files changed, 297 insertions(+), 358 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java index e3bd544adf..e2aa6d3daf 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java @@ -18,11 +18,11 @@ import static com.fasterxml.jackson.databind.PropertyNamingStrategies.KEBAB_CASE; import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; -import static java.lang.System.setProperty; -import static java.util.concurrent.Executors.newScheduledThreadPool; import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; import static jakarta.ws.rs.core.Response.status; import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static java.lang.System.setProperty; +import static java.util.concurrent.Executors.newScheduledThreadPool; import static org.apache.cxf.message.Message.PROTOCOL_HEADERS; import static org.apache.cxf.phase.Phase.RECEIVE; import static org.apache.cxf.transport.http.AbstractHTTPDestination.HTTP_REQUEST; @@ -36,14 +36,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; -import jakarta.annotation.PostConstruct; -import jakarta.servlet.ServletRequest; -import javax.validation.ValidationException; -import jakarta.ws.rs.ApplicationPath; -import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.ext.ExceptionMapper; - import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.endpoint.Server; import org.apache.cxf.interceptor.Fault; @@ -77,6 +69,13 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.ServletRequest; +import jakarta.validation.ValidationException; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; +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.AllocatorProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.AuthProperties; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java index f910afe662..0fe091980d 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/SpallocProperties.java @@ -23,17 +23,6 @@ import java.time.Duration; import java.util.Set; -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.Email; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.core.io.Resource; @@ -41,6 +30,16 @@ import com.google.errorprone.annotations.Keep; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.utils.validation.IPAddress; import uk.ac.manchester.spinnaker.utils.validation.TCPPort; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java index f2805208c1..47a4b3d0f6 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminAPI.java @@ -31,13 +31,12 @@ import java.net.URI; import java.util.Map; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - import org.springframework.security.access.prepost.PreAuthorize; import io.swagger.v3.oas.annotations.Hidden; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminController.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminController.java index ed6ec0d83e..600126f2cc 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminController.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminController.java @@ -22,14 +22,6 @@ import java.util.Objects; import java.util.concurrent.CompletableFuture; -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import org.springframework.scheduling.annotation.Async; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.ui.ModelMap; @@ -45,6 +37,13 @@ import com.google.errorprone.annotations.Keep; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.alloc.model.BoardRecord; import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; import uk.ac.manchester.spinnaker.alloc.model.TagList; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 8c91aa9c08..be49d32063 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -35,14 +35,6 @@ import java.util.Optional; import java.util.Set; -import javax.validation.Valid; -import javax.validation.ValidatorFactory; -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 org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -61,6 +53,13 @@ import com.google.errorprone.annotations.RestrictedApi; import jakarta.annotation.PostConstruct; +import jakarta.validation.Valid; +import jakarta.validation.ValidatorFactory; +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 uk.ac.manchester.spinnaker.alloc.ForTestingOnly; import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Update; diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index bfb7886ccf..4e4b3e46f9 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -40,10 +40,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.function.Function; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -55,6 +51,9 @@ import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.alloc.SpallocProperties; import uk.ac.manchester.spinnaker.alloc.SpallocProperties.StateControlProperties; import uk.ac.manchester.spinnaker.alloc.allocator.Epochs; 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 c5e610b8a8..ad9d0ec8f4 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 @@ -30,16 +30,15 @@ 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 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; 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 69f8a81246..3c7f5775b6 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 @@ -21,11 +21,11 @@ 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 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/SaneParameter.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/SaneParameter.java index efdaf7bcdf..1024f37c65 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 @@ -26,10 +26,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 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 e986b9131f..69c9f94ab4 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 @@ -45,17 +45,16 @@ 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; import com.fasterxml.jackson.databind.JsonMappingException; 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; 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 1695ea4899..2ad175803a 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 @@ -22,11 +22,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; 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 b08842cbd8..eb68cdf746 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 @@ -21,13 +21,12 @@ 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; 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 3598b2e815..30df02068c 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 @@ -18,12 +18,12 @@ 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. * 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 9e0818bf2b..d5d25fb122 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 @@ -24,12 +24,11 @@ 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; /** 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 2594e5ce15..a87184d605 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 @@ -25,9 +25,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; 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 4ecc2625c7..caddfaeccc 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 @@ -21,10 +21,10 @@ import java.time.Instant; import java.util.Optional; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; /** * Entry in a table of machines. The table is like this: 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 6f32a3a0b2..0f21e91325 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 @@ -22,10 +22,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; 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 24bbe7774e..c5ab93b85f 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 @@ -22,9 +22,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: 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 ed7b2ffaa2..0b47e62b4f 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.HashSet; 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.MappableIterable; 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 91e5b9e6d9..421a80c189 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 @@ -20,10 +20,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. * 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 174ae93c6b..a370a2c79f 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 @@ -18,9 +18,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 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 ffbab78626..92e09a7308 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 @@ -26,8 +26,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 330bde715f..1d9e16b97c 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 @@ -26,16 +26,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; 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 93adaf801c..b48f2d0f4e 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 @@ -21,17 +21,16 @@ 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.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; 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 a421546830..961cdfd916 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 @@ -20,13 +20,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; 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 bdc4e6df16..38943801ee 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 @@ -16,11 +16,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; /** 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 4451f0206d..d1fb98162f 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 @@ -42,12 +42,6 @@ import static uk.ac.manchester.spinnaker.alloc.web.WebServiceComponentNames.SERV; import static uk.ac.manchester.spinnaker.alloc.web.WebServiceComponentNames.WAIT; -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 org.apache.cxf.jaxrs.model.wadl.Description; import org.springframework.security.access.prepost.PreAuthorize; @@ -60,6 +54,11 @@ 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; 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 6a053b0298..b1170d37d5 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,8 +20,6 @@ import java.security.Principal; -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; @@ -33,6 +31,7 @@ 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 8b2f882590..231dc81502 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 @@ -29,8 +29,6 @@ import java.security.Principal; -import javax.validation.Valid; - import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -50,6 +48,7 @@ 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/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 f98a1c6e8a..71a269511e 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 @@ -35,13 +35,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; diff --git a/SpiNNaker-comms/pom.xml b/SpiNNaker-comms/pom.xml index b73996c964..8cf8c1dfff 100644 --- a/SpiNNaker-comms/pom.xml +++ b/SpiNNaker-comms/pom.xml @@ -54,7 +54,7 @@ along with this program. If not, see . 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 dcc991a37a..7848eb25f8 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 @@ -22,9 +22,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; @@ -34,6 +31,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/CreateJob.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/CreateJob.java index 8d39092023..b528fe610e 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 @@ -22,14 +22,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; 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 5defdf7686..9a30fd2c0b 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 @@ -26,11 +26,10 @@ 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.connections.EIEIOConnection; import uk.ac.manchester.spinnaker.connections.SCPConnection; import uk.ac.manchester.spinnaker.machine.HasChipLocation; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java index 2f865ee08a..caa5f03302 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/BMPConnectionData.java @@ -27,8 +27,7 @@ import java.util.Collection; import java.util.List; -import javax.validation.Valid; - +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.board.BMPBoard; import uk.ac.manchester.spinnaker.machine.board.BMPCoords; import uk.ac.manchester.spinnaker.utils.validation.IPAddress; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index d3ffa43ae3..e5c7fadc54 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -62,10 +62,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.validation.Valid; - import org.slf4j.Logger; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.Direction; import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java index b48714bf22..7f3e610c1c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java @@ -22,10 +22,9 @@ import java.util.Map; import java.util.Set; -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.CoreLocation; import uk.ac.manchester.spinnaker.machine.CoreSubsets; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java index 7cceffb2a9..bcb53900c8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java @@ -22,8 +22,7 @@ import java.nio.ByteBuffer; -import javax.validation.Valid; - +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.HasChipLocation; import uk.ac.manchester.spinnaker.machine.ValidP; import uk.ac.manchester.spinnaker.messages.model.AppID; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java index ca71192a3a..cd556a883a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java @@ -31,12 +31,11 @@ import java.nio.ByteBuffer; import java.util.Arrays; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - import org.slf4j.Logger; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import uk.ac.manchester.spinnaker.machine.HasChipLocation; import uk.ac.manchester.spinnaker.machine.tags.TagID; import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java index 8b7f78d51c..10c0cc8cb1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java @@ -30,9 +30,8 @@ import java.nio.ByteBuffer; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.HasChipLocation; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.tags.TagID; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java index e8ad51473c..c1a33dc132 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPHeader.java @@ -24,9 +24,8 @@ import java.nio.ByteBuffer; import java.util.Map; -import javax.validation.Valid; -import javax.validation.constraints.PositiveOrZero; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.messages.SerializableMessage; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/Configuration.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/Configuration.java index d3a132b422..7298c0d248 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/Configuration.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/Configuration.java @@ -43,10 +43,6 @@ import java.util.List; import java.util.Map; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import org.apache.commons.configuration2.INIConfiguration; import org.apache.commons.configuration2.SubnodeConfiguration; import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; @@ -58,6 +54,9 @@ import org.apache.commons.configuration2.io.HomeDirectoryLocationStrategy; import org.apache.commons.configuration2.io.ProvidedURLLocationStrategy; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.utils.validation.TCPPort; /** A spalloc configuration loaded from a file. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/CreateJob.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/CreateJob.java index 557b9bbe37..caab0707b6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/CreateJob.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/CreateJob.java @@ -33,13 +33,12 @@ import java.util.List; import java.util.Map; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import com.google.errorprone.annotations.CanIgnoreReturnValue; +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.ValidTriadHeight; import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth; import uk.ac.manchester.spinnaker.machine.board.ValidTriadX; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocAPI.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocAPI.java index 03706740e2..b8c1f2f574 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocAPI.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocAPI.java @@ -20,12 +20,11 @@ import java.util.List; import java.util.Map; -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 jakarta.validation.Valid; +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.HasChipLocation; import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; import uk.ac.manchester.spinnaker.machine.board.TriadCoords; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java index a71df2dd82..241587d0d9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/Connection.java @@ -21,8 +21,6 @@ import java.util.Objects; -import javax.validation.Valid; - import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -30,6 +28,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; 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.utils.validation.IPAddress; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java index dc34524bda..5b12800eb1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardAtPositionCommand.java @@ -16,9 +16,8 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java index 36ca75f6c7..5b1182ee6b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/GetBoardPositionCommand.java @@ -16,9 +16,8 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import uk.ac.manchester.spinnaker.machine.board.TriadCoords; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobState.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobState.java index 4ae7e7d532..cc5a09e58a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobState.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/JobState.java @@ -16,12 +16,12 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import javax.validation.constraints.Positive; - import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.google.errorprone.annotations.Immutable; +import jakarta.validation.constraints.Positive; + /** * A description of the state of a job, in terms of its state, whether its * boards are powered, the advised keep-alive polling interval and the reason diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java index e3986abae0..7fdb15627c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardLogicalCommand.java @@ -16,9 +16,8 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import uk.ac.manchester.spinnaker.machine.board.TriadCoords; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java index 069b68b15f..5196ac9f2e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/WhereIsMachineBoardPhysicalCommand.java @@ -16,10 +16,9 @@ */ package uk.ac.manchester.spinnaker.spalloc.messages; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java index 6e706e7301..ba5f42c5bb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java @@ -40,12 +40,11 @@ import java.util.Collection; import java.util.Set; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; - import com.google.errorprone.annotations.CheckReturnValue; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import uk.ac.manchester.spinnaker.machine.MemoryLocation; import uk.ac.manchester.spinnaker.machine.board.BMPBoard; import uk.ac.manchester.spinnaker.machine.board.BMPCoords; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 6960c6a89d..2b4baf6ee0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -76,15 +76,14 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadLocalRandom; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - import org.slf4j.Logger; import com.google.errorprone.annotations.CheckReturnValue; import com.google.errorprone.annotations.MustBeClosed; import com.google.errorprone.annotations.concurrent.GuardedBy; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.connections.BMPConnection; import uk.ac.manchester.spinnaker.connections.BootConnection; import uk.ac.manchester.spinnaker.connections.ConnectionSelector; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java index 0438a88f69..672a98b135 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java @@ -50,14 +50,13 @@ import java.util.Set; import java.util.TreeMap; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import com.google.errorprone.annotations.CheckReturnValue; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.connections.ConnectionSelector; import uk.ac.manchester.spinnaker.connections.SCPConnection; import uk.ac.manchester.spinnaker.connections.SDPConnection; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UnimplementedBMPTransceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UnimplementedBMPTransceiver.java index 4a4b1b533e..5fdef120c0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UnimplementedBMPTransceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UnimplementedBMPTransceiver.java @@ -22,9 +22,8 @@ import java.nio.ByteBuffer; import java.util.Collection; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - +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; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Gather.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Gather.java index 5163c4f99b..80b9216dd5 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Gather.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Gather.java @@ -22,12 +22,11 @@ import java.io.IOException; import java.util.List; -import javax.validation.Valid; - import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.ValidP; import uk.ac.manchester.spinnaker.machine.ValidX; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Monitor.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Monitor.java index 7de07105f8..58e4e6d9f8 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Monitor.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Monitor.java @@ -22,12 +22,11 @@ import java.io.IOException; import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.ValidP; import uk.ac.manchester.spinnaker.machine.ValidX; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java index 6ae80f87b6..2cb88a36ad 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/request/Vertex.java @@ -16,15 +16,13 @@ */ package uk.ac.manchester.spinnaker.front_end.download.request; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnore; - import static com.fasterxml.jackson.annotation.JsonFormat.Shape.OBJECT; -import javax.validation.constraints.NotNull; - +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.MemoryLocation; /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/IobufRequest.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/IobufRequest.java index 1832434952..4f7e3c6426 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/IobufRequest.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/IobufRequest.java @@ -26,15 +26,14 @@ import java.util.List; import java.util.Map; -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotNull; - import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.CoreSubsets; /** diff --git a/SpiNNaker-machine/pom.xml b/SpiNNaker-machine/pom.xml index 31a9e8ebc9..a6012babe2 100644 --- a/SpiNNaker-machine/pom.xml +++ b/SpiNNaker-machine/pom.xml @@ -40,7 +40,7 @@ along with this program. If not, see . com.fasterxml.jackson.module - jackson-module-jaxb-annotations + jackson-module-jakarta-xmlbind-annotations jakarta.validation diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java index 6e10d0601d..c059551028 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Chip.java @@ -30,7 +30,7 @@ import java.util.Objects; import java.util.TreeMap; -import javax.validation.Valid; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.bean.ChipBean; import uk.ac.manchester.spinnaker.machine.tags.TagID; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java index 4d754b5231..a8b7c51b0a 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java @@ -27,8 +27,7 @@ import java.util.Set; import java.util.TreeMap; -import javax.validation.Valid; - +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.utils.DoubleMapIterator; import uk.ac.manchester.spinnaker.utils.MappableIterable; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java index 12c57ae12d..92853c1669 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Link.java @@ -21,12 +21,12 @@ import java.util.Objects; -import javax.validation.Valid; - import org.slf4j.Logger; import com.google.errorprone.annotations.Immutable; +import jakarta.validation.Valid; + /** * Represents a directional link between SpiNNaker chips in the machine. * diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java index b637f349a8..addfd398f1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Machine.java @@ -40,7 +40,7 @@ import java.util.SortedMap; import java.util.TreeMap; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.slf4j.Logger; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java index 5496227545..4bbf5edfa3 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/RoutingEntry.java @@ -26,7 +26,7 @@ import java.util.LinkedHashSet; import java.util.Set; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import com.google.errorprone.annotations.Immutable; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java index 1968d885e6..34ebd16bb0 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java @@ -27,11 +27,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; /** * Validates that a machine's height (in chips) is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java index a2a0aa563a..8f1dcbec17 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java @@ -27,11 +27,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; /** * Validates that a machine's width (in chips) is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java index 93daa200d4..ec49eff1b1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a chip processor number is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java index 9555a0f0a7..bc78eeb49a 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a chip X coordinate is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java index 60effdfe0d..b21028e953 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a chip Y coordinate is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java index 0c24111b8e..16267ec006 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipBean.java @@ -16,14 +16,13 @@ */ package uk.ac.manchester.spinnaker.machine.bean; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonFormat; import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; -import javax.validation.Valid; - +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.Chip; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java index b97988db29..1473a1c07a 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/ChipDetails.java @@ -25,14 +25,13 @@ import java.util.List; import java.util.Set; -import javax.validation.Valid; -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.machine.Chip; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.Direction; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java index eca1e58edb..2120c9a331 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/LinkBean.java @@ -16,12 +16,11 @@ */ package uk.ac.manchester.spinnaker.machine.bean; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.Chip; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.Direction; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java index dd96c5e045..1b562b0da6 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/bean/MachineBean.java @@ -16,12 +16,12 @@ */ package uk.ac.manchester.spinnaker.machine.bean; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; -import javax.validation.Valid; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.Machine; import uk.ac.manchester.spinnaker.machine.MachineDimensions; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java index d7deff7de8..aeaa2d0251 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java @@ -28,10 +28,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 a board number is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java index 2c88a84fcc..b5932bff51 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java @@ -27,10 +27,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 a cabinet number is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java index 3a7291aa47..50cf431ca1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java @@ -27,10 +27,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 a frame number is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java index 8d4aaaa217..1d2fa01144 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; /** * Validates that a machine's depth is in a sane range. Note that only machines diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java index fe3fa14e31..282f00490f 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; /** * Validates that a machine's height (in triads) is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java index 9ba3a7a832..febfbcc3ed 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; /** * Validates that a machine's width (in triads) is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java index 691ab06ca4..dc48cfa913 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a triad X coordinate is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java index e8757ed3b7..5daf4bbd17 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a triad Y coordinate is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java index e1c061b430..7d447667d8 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java @@ -26,11 +26,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; /** * Validates that a triad Z coordinate is in a sane range. diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java index 8ed0362c5f..cba952cc97 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/datalinks/AbstractDataLink.java @@ -19,10 +19,9 @@ import java.net.InetAddress; import java.util.Objects; -import javax.validation.Valid; - import com.google.errorprone.annotations.Immutable; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.Direction; import uk.ac.manchester.spinnaker.machine.HasChipLocation; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java index a1137013cd..1b6a68811b 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/IPTag.java @@ -23,10 +23,9 @@ import java.net.UnknownHostException; import java.util.Objects; -import javax.validation.Valid; - import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.ChipLocation; /** diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java index d5155c22de..69d1103154 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/ReverseIPTag.java @@ -19,8 +19,7 @@ import java.net.InetAddress; import java.util.Objects; -import javax.validation.Valid; - +import jakarta.validation.Valid; import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java index 336d7904a4..0842af60d0 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/Tag.java @@ -21,8 +21,7 @@ import java.net.InetAddress; import java.util.Objects; -import javax.validation.constraints.NotNull; - +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.utils.validation.UDPPort; /** Common properties of SpiNNaker IP tags and reverse IP tags. */ diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java index 00e9a33148..6b3d78e725 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java @@ -27,10 +27,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 a number looks like a tag identifier. Always accepts diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java index beaa9b9e03..f9c2c0ffb1 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java @@ -21,13 +21,12 @@ import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - import org.python.core.PyObject; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.utils.validation.IPAddress; import uk.ac.manchester.spinnaker.utils.validation.TCPPort; diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java index d79a5c4ff7..c3dd44b826 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java @@ -28,17 +28,16 @@ import java.util.Map; import java.util.Set; -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - import org.python.core.PyObject; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.errorprone.annotations.Keep; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import uk.ac.manchester.spinnaker.machine.board.BMPCoords; import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; import uk.ac.manchester.spinnaker.machine.board.TriadCoords; diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java index c53172b1c1..bbe6b94f59 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java @@ -19,11 +19,10 @@ import java.nio.ByteBuffer; import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java index 40d3ce5e83..df679f53b9 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java @@ -19,9 +19,8 @@ import java.nio.ByteBuffer; import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.Positive; - +import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java index 7b33787a99..2567bdb0e6 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyInformation.java @@ -16,7 +16,7 @@ */ package uk.ac.manchester.spinnaker.storage; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; /** * Information about the proxy to allow connection. diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/IPAddress.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/IPAddress.java index 42efcce786..078485a957 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/IPAddress.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/IPAddress.java @@ -30,10 +30,10 @@ import java.net.UnknownHostException; import java.util.regex.Pattern; -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 a string looks like an IP address. A string is considered to diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java index 533857bd71..9a9ff2b4c5 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java @@ -27,10 +27,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 a number looks like a TCP port. Always accepts {@code null}. diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java index 8d326a452d..ae5ec5bf53 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java @@ -27,10 +27,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 a number looks like a UDP port. Always accepts {@code null}. diff --git a/pom.xml b/pom.xml index 191deb8e08..2c83d7f1b8 100644 --- a/pom.xml +++ b/pom.xml @@ -341,7 +341,7 @@ along with this program. If not, see . jakarta.validation jakarta.validation-api - 2.0.2 + 3.0.2 com.google.errorprone From 5793339722ba5199183e846d1b13a47c8b0c70c9 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 16:04:37 +0000 Subject: [PATCH 039/194] PostFilter should just be on interface methods Something has changed about exactly how things are looked up, so where we used to have the same annotation twice and things worked, that doesn't fly any more. I'm not 100% what changed, but it did... --- .../uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java | 4 ---- 1 file changed, 4 deletions(-) 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 3e20ac336b..28ecde2912 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,7 +32,6 @@ 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.model.Utils.chip; -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; @@ -49,7 +48,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; @@ -338,7 +336,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)); } @@ -351,7 +348,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); From e7f4dd451620e111cc6f2d927c061330eeb53f28 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 3 Jan 2023 16:11:57 +0000 Subject: [PATCH 040/194] Fix CodeQL workflow --- .github/workflows/codeql-analysis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6bf77681aa..dc197c9b8a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -52,6 +52,12 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + # CodeQL defaults to wrong version without this. + - name: Initialize Java + uses: actions/setup-java@v1 + with: + java-version: 17 + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 From d6bda9ca918655f14a86727402f930b8db9b5e6b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 4 Jan 2023 15:34:38 +0000 Subject: [PATCH 041/194] New style switch --- .../spinnaker/alloc/bmp/BMPController.java | 15 +- .../spinnaker/alloc/bmp/FirmwareLoader.java | 12 +- .../spinnaker/alloc/compat/Utils.java | 20 ++- .../spinnaker/alloc/compat/V1CompatTask.java | 136 +++++++++--------- .../manchester/spinnaker/alloc/db/Utils.java | 125 ++++++---------- .../spinnaker/alloc/client/ClientSession.java | 17 +-- .../manchester/spinnaker/io/AbstractIO.java | 19 +-- .../messages/eieio/EIEIODataMessage.java | 76 ++++------ .../messages/eieio/KeyDataElement.java | 11 +- .../messages/eieio/KeyPayloadDataElement.java | 21 +-- .../spinnaker/messages/model/ChipInfo.java | 19 +-- .../model/SystemVariableDefinition.java | 46 +++--- .../notification/NotificationMessage.java | 17 +-- .../spinnaker/transceiver/FillDataType.java | 40 +++--- .../transceiver/ProcessException.java | 5 +- .../spinnaker/transceiver/Transceiver.java | 27 ++-- .../spinnaker/data_spec/Functions.java | 19 +-- .../spinnaker/data_spec/Generator.java | 96 +++++++------ .../front_end/CommandLineInterface.java | 3 +- .../spinnaker/front_end/DebuggingUtils.java | 15 +- .../spinnaker/machine/Direction.java | 22 ++- .../spinnaker/machine/board/BMPCoords.java | 13 +- .../machine/board/DeserializerHelper.java | 16 +-- .../machine/board/PhysicalCoords.java | 18 +-- .../sqlite/SQLiteConnectionManager.java | 6 +- 25 files changed, 330 insertions(+), 484 deletions(-) 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 ae5a3d7faa..db0ea4806d 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 @@ -980,17 +980,10 @@ boolean perform(SpiNNakerControl controller) throws InterruptedException { return bmpAction(() -> { switch (op) { - case WRITE: - writeBlacklist(controller); - break; - case READ: - readBlacklist(controller); - break; - case GET_SERIAL: - readSerial(controller); - break; - default: - throw new IllegalArgumentException(); + case WRITE -> writeBlacklist(controller); + case READ -> readBlacklist(controller); + case GET_SERIAL -> readSerial(controller); + default -> throw new IllegalArgumentException(); } }, e -> { cleanupTasks.add(curry(this::failed, e)); 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 b3b274ad02..c1eece6f61 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 @@ -416,15 +416,9 @@ private void listFPGABootChunks() 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); } } } 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 10661e1e6a..94e9b4bffa 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 @@ -225,18 +225,14 @@ static Double timestamp(Instant instant) { * @return The converted state. */ static State state(Job job) { - switch (job.getState()) { - 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 (job.getState()) { + case QUEUED -> State.QUEUED; + case POWER -> State.POWER; + case READY -> State.READY; + case DESTROYED -> State.DESTROYED; + default -> State.UNKNOWN; + }; } /** 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 e986b9131f..ba06e87940 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 @@ -263,13 +263,11 @@ 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); @@ -442,73 +440,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")) { @@ -516,21 +517,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."; @@ -545,13 +547,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/db/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Utils.java index e1cb21674b..2715ab4c72 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 @@ -152,91 +152,48 @@ public static DataAccessException mapException(SQLException exception, "$1"); replaced = true; } - switch (exn.getResultCode()) { - case SQLITE_CONSTRAINT: - case SQLITE_CONSTRAINT_CHECK: - case SQLITE_CONSTRAINT_COMMITHOOK: - case SQLITE_CONSTRAINT_FOREIGNKEY: - case SQLITE_CONSTRAINT_FUNCTION: - case SQLITE_CONSTRAINT_PRIMARYKEY: - case SQLITE_CONSTRAINT_UNIQUE: - case SQLITE_CONSTRAINT_NOTNULL: - case SQLITE_CONSTRAINT_TRIGGER: - case SQLITE_CONSTRAINT_ROWID: - case SQLITE_CONSTRAINT_VTAB: - case SQLITE_MISMATCH: - return restack(new DataIntegrityViolationException(msg, exn)); - - case SQLITE_BUSY: - case SQLITE_BUSY_RECOVERY: - case SQLITE_BUSY_SNAPSHOT: - case SQLITE_LOCKED: - case SQLITE_LOCKED_SHAREDCACHE: - return restack(new PessimisticLockingFailureException(msg, exn)); - - case SQLITE_ABORT: - case SQLITE_ABORT_ROLLBACK: - case SQLITE_FULL: - case SQLITE_EMPTY: - return restack(new RecoverableDataAccessException(msg, exn)); - - case SQLITE_SCHEMA: - case SQLITE_TOOBIG: - case SQLITE_RANGE: - return restack( - new InvalidDataAccessResourceUsageException(msg, exn)); - - case SQLITE_IOERR: - case SQLITE_IOERR_SHORT_READ: - case SQLITE_IOERR_READ: - case SQLITE_IOERR_WRITE: - case SQLITE_IOERR_FSYNC: - case SQLITE_IOERR_DIR_FSYNC: - case SQLITE_IOERR_TRUNCATE: - case SQLITE_IOERR_FSTAT: - case SQLITE_IOERR_UNLOCK: - case SQLITE_IOERR_RDLOCK: - case SQLITE_IOERR_DELETE: - case SQLITE_IOERR_NOMEM: - case SQLITE_IOERR_ACCESS: - case SQLITE_IOERR_CHECKRESERVEDLOCK: - case SQLITE_IOERR_LOCK: - case SQLITE_IOERR_CLOSE: - case SQLITE_IOERR_SHMOPEN: - case SQLITE_IOERR_SHMSIZE: - case SQLITE_IOERR_SHMMAP: - case SQLITE_IOERR_SEEK: - case SQLITE_IOERR_DELETE_NOENT: - case SQLITE_IOERR_MMAP: - case SQLITE_IOERR_GETTEMPPATH: - case SQLITE_IOERR_CONVPATH: - case SQLITE_PERM: - case SQLITE_READONLY: - case SQLITE_READONLY_RECOVERY: - case SQLITE_READONLY_CANTLOCK: - case SQLITE_READONLY_ROLLBACK: - case SQLITE_READONLY_DBMOVED: - case SQLITE_AUTH: - case SQLITE_MISUSE: - case SQLITE_NOLFS: - case SQLITE_CORRUPT: - case SQLITE_CORRUPT_VTAB: - case SQLITE_CANTOPEN: - case SQLITE_CANTOPEN_ISDIR: - case SQLITE_CANTOPEN_FULLPATH: - case SQLITE_CANTOPEN_CONVPATH: - case SQLITE_NOTADB: - case SQLITE_FORMAT: - return restack(new DataAccessResourceFailureException(msg, exn)); - - default: - if (replaced) { - return restack(new BadSqlGrammarException(msg, + return switch (exn.getResultCode()) { + case SQLITE_CONSTRAINT, SQLITE_CONSTRAINT_CHECK, + SQLITE_CONSTRAINT_COMMITHOOK, SQLITE_CONSTRAINT_FOREIGNKEY, + SQLITE_CONSTRAINT_FUNCTION, SQLITE_CONSTRAINT_PRIMARYKEY, + SQLITE_CONSTRAINT_UNIQUE, SQLITE_CONSTRAINT_NOTNULL, + SQLITE_CONSTRAINT_TRIGGER, SQLITE_CONSTRAINT_ROWID, + SQLITE_CONSTRAINT_VTAB, SQLITE_MISMATCH -> + restack(new DataIntegrityViolationException(msg, exn)); + + case SQLITE_BUSY, SQLITE_BUSY_RECOVERY, SQLITE_BUSY_SNAPSHOT, + SQLITE_BUSY_TIMEOUT, SQLITE_LOCKED, SQLITE_LOCKED_SHAREDCACHE -> + restack(new PessimisticLockingFailureException(msg, exn)); + + case SQLITE_ABORT, SQLITE_ABORT_ROLLBACK, SQLITE_FULL, SQLITE_EMPTY -> + restack(new RecoverableDataAccessException(msg, exn)); + + case SQLITE_SCHEMA, SQLITE_TOOBIG, SQLITE_RANGE -> + restack(new InvalidDataAccessResourceUsageException(msg, exn)); + + case SQLITE_IOERR, SQLITE_IOERR_SHORT_READ, SQLITE_IOERR_READ, + SQLITE_IOERR_WRITE, SQLITE_IOERR_FSYNC, SQLITE_IOERR_DIR_FSYNC, + SQLITE_IOERR_TRUNCATE, SQLITE_IOERR_FSTAT, SQLITE_IOERR_UNLOCK, + SQLITE_IOERR_RDLOCK, SQLITE_IOERR_DELETE, SQLITE_IOERR_NOMEM, + SQLITE_IOERR_ACCESS, SQLITE_IOERR_CHECKRESERVEDLOCK, + SQLITE_IOERR_LOCK, SQLITE_IOERR_CLOSE, SQLITE_IOERR_SHMOPEN, + SQLITE_IOERR_SHMSIZE, SQLITE_IOERR_SHMMAP, SQLITE_IOERR_SEEK, + SQLITE_IOERR_DELETE_NOENT, SQLITE_IOERR_MMAP, + SQLITE_IOERR_GETTEMPPATH, SQLITE_IOERR_CONVPATH, SQLITE_PERM, + SQLITE_READONLY, SQLITE_READONLY_RECOVERY, + SQLITE_READONLY_CANTLOCK, SQLITE_READONLY_ROLLBACK, + SQLITE_READONLY_DBMOVED, SQLITE_AUTH, SQLITE_MISUSE, + SQLITE_NOLFS, SQLITE_CORRUPT, SQLITE_CORRUPT_VTAB, + SQLITE_CANTOPEN, SQLITE_CANTOPEN_ISDIR, + SQLITE_CANTOPEN_FULLPATH, SQLITE_CANTOPEN_CONVPATH, + SQLITE_NOTADB, SQLITE_FORMAT -> + restack(new DataAccessResourceFailureException(msg, exn)); + + default -> restack(replaced + ? new BadSqlGrammarException(msg, trimSQLComments(sql), exn) + : new UncategorizedSQLException("general SQL exception", trimSQLComments(sql), exn)); - } - return restack(new UncategorizedSQLException( - "general SQL exception", trimSQLComments(sql), exn)); - } + }; } // 2 = restack() and mapException() themselves 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 c794a318b2..f68d045480 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 @@ -289,19 +289,16 @@ 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 MSG_TO: // Never sent - default: - log.error("unexpected message code: {}", code); + "unrecognised channel").receive(message); + // case MSG_TO -> // Never sent by service, only by us + default -> log.error("unexpected message code: {}", code); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/AbstractIO.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/AbstractIO.java index df77415173..25d781368d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/AbstractIO.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/io/AbstractIO.java @@ -112,19 +112,12 @@ public interface AbstractIO extends AutoCloseable { default void seek(int numBytes, Seek whence) throws IOException, ProcessException { switch (whence) { - case SET: - seek(numBytes); - break; - case CUR: - seek(numBytes + tell()); - break; - case END: - seek(numBytes + size()); - break; - default: - // CHECKSTYLE:OFF - throw new IllegalArgumentException(); - // CHECKSTYLE:ON + case SET -> seek(numBytes); + case CUR -> seek(numBytes + tell()); + case END -> seek(numBytes + size()); + // CHECKSTYLE:OFF + default -> throw new IllegalArgumentException(); + // CHECKSTYLE:ON } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java index a45fce5428..0e58cd5388 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java @@ -215,28 +215,15 @@ public AbstractDataElement next() { throw new NoSuchElementException("read all elements"); } elementsRead++; - int key; - Integer payload; - switch (header.eieioType) { - case KEY_16_BIT: - key = d.getShort(); - payload = null; - break; - case KEY_PAYLOAD_16_BIT: - key = d.getShort(); - payload = (int) d.getShort(); - break; - case KEY_32_BIT: - key = d.getInt(); - payload = null; - break; - case KEY_PAYLOAD_32_BIT: - key = d.getInt(); - payload = d.getInt(); - break; - default: - throw new IllegalStateException(); - } + int key = switch (header.eieioType) { + case KEY_16_BIT, KEY_PAYLOAD_16_BIT -> d.getShort(); + case KEY_32_BIT, KEY_PAYLOAD_32_BIT -> d.getInt(); + }; + Integer payload = switch (header.eieioType) { + case KEY_PAYLOAD_16_BIT -> (int) d.getShort(); + case KEY_PAYLOAD_32_BIT -> d.getInt(); + default -> null; + }; if (header.prefix != null) { key |= header.prefix << header.prefixType.shift; } @@ -247,10 +234,9 @@ public AbstractDataElement next() { payload = header.payloadBase; } } - if (payload == null) { - return new KeyDataElement(key); - } - return new KeyPayloadDataElement(key, payload, header.isTime); + return (payload == null) ? new KeyDataElement(key) + : new KeyPayloadDataElement(key, payload, + header.isTime); } }; } @@ -328,12 +314,9 @@ private Header(ByteBuffer buffer) { count = buffer.get(); byte flags = buffer.get(); boolean havePrefix = bit(flags, PREFIX_BIT) != 0; - if (havePrefix) { - prefixType = - EIEIOPrefix.getByValue(bit(flags, PREFIX_TYPE_BIT)); - } else { - prefixType = null; - } + prefixType = havePrefix + ? EIEIOPrefix.getByValue(bit(flags, PREFIX_TYPE_BIT)) + : null; boolean havePayload = bit(flags, PAYLOAD_BIT) != 0; isTime = bit(flags, TIME_BIT) != 0; eieioType = EIEIOType.getByValue(bits(flags, TYPE_BITS)); @@ -344,18 +327,12 @@ private Header(ByteBuffer buffer) { prefix = null; } if (havePayload) { - switch (eieioType) { - case KEY_PAYLOAD_16_BIT: - case KEY_16_BIT: - payloadBase = toUnsignedInt(buffer.getShort()); - break; - case KEY_PAYLOAD_32_BIT: - case KEY_32_BIT: - payloadBase = buffer.getInt(); - break; - default: - payloadBase = null; - } + payloadBase = switch (eieioType) { + case KEY_PAYLOAD_16_BIT, KEY_16_BIT -> + toUnsignedInt(buffer.getShort()); + case KEY_PAYLOAD_32_BIT, KEY_32_BIT -> buffer.getInt(); + default -> null; + }; } else { payloadBase = null; } @@ -443,16 +420,11 @@ public void addToBuffer(ByteBuffer buffer) { return; } switch (eieioType) { - case KEY_PAYLOAD_16_BIT: - case KEY_16_BIT: + case KEY_PAYLOAD_16_BIT, KEY_16_BIT -> buffer.putShort((short) payloadBase.intValue()); - return; - case KEY_PAYLOAD_32_BIT: - case KEY_32_BIT: + case KEY_PAYLOAD_32_BIT, KEY_32_BIT -> buffer.putInt(payloadBase.intValue()); - return; - default: - throw new IllegalStateException("unexpected EIEIO type"); + default -> throw new IllegalStateException("unexpected EIEIO type"); } } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java index 41bfdcba3d..5e837ea89d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java @@ -38,14 +38,9 @@ public final void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { + " payload"); } switch (eieioType) { - case KEY_16_BIT: - buffer.putShort((short) key); - return; - case KEY_32_BIT: - buffer.putInt(key); - return; - default: - throw new IllegalArgumentException("Unknown type"); + case KEY_16_BIT -> buffer.putShort((short) key); + case KEY_32_BIT -> buffer.putInt(key); + default -> throw new IllegalArgumentException("Unknown type"); } } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java index 01ab282dcf..b53a69d941 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java @@ -28,9 +28,13 @@ public class KeyPayloadDataElement implements AbstractDataElement { /** * Create a data element. - * @param key The key in the element. - * @param payload The payload in the element. - * @param isTimestamp Whether this is a timestamp. + * + * @param key + * The key in the element. + * @param payload + * The payload in the element. + * @param isTimestamp + * Whether this is a timestamp. */ public KeyPayloadDataElement(int key, int payload, boolean isTimestamp) { this.key = key; @@ -51,16 +55,15 @@ public final void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { + " payload"); } switch (eieioType) { - case KEY_PAYLOAD_16_BIT: + case KEY_PAYLOAD_16_BIT -> { buffer.putShort((short) key); buffer.putShort((short) payload); - return; - case KEY_PAYLOAD_32_BIT: + } + case KEY_PAYLOAD_32_BIT -> { buffer.putInt(key); buffer.putInt(payload); - return; - default: - throw new IllegalArgumentException("Unknown type"); + } + default -> throw new IllegalArgumentException("Unknown type"); } } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java index b62ddb42d5..5347fa1746 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java @@ -187,19 +187,12 @@ public ChipInfo(ByteBuffer systemData) { } private int read(SystemVariableDefinition var) { - switch (var.type) { - case BYTE: - return systemData.get(systemData.position() + var.offset); - case INT: - return systemData.getInt(systemData.position() + var.offset); - case SHORT: - return systemData.getShort(systemData.position() + var.offset); - case BYTE_ARRAY: - case LONG: - case ADDRESS: - default: - throw new IllegalArgumentException(); - } + return switch (var.type) { + case BYTE -> systemData.get(systemData.position() + var.offset); + case INT -> systemData.getInt(systemData.position() + var.offset); + case SHORT -> systemData.getShort(systemData.position() + var.offset); + default -> throw new IllegalArgumentException(); + }; } private long readLong(SystemVariableDefinition var) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java index e157920162..01a0d75fc2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java @@ -288,17 +288,16 @@ public Object getDefault() { * @return The default value, or a copy of it if the type of the value is an * array. */ - @SuppressWarnings("checkstyle:JavadocMethod") // AssertionError not in signature because it should be unreachable public Object getDefault() { - switch (type) { - case BYTE_ARRAY: + return switch (type) { + // CHECKSTYLE:OFF + case BYTE_ARRAY -> throw new AssertionError("unreachable location reached"); - case ADDRESS: - return defAddr; - default: - return def; - } + // CHECKSTYLE:ON + case ADDRESS -> defAddr; + default -> def; + }; } /** @return Whether this is a variable with a usefully-defined default. */ @@ -322,28 +321,15 @@ public boolean isDefaultSpecified() { */ public void addToBuffer(Object value, ByteBuffer buffer) { switch (type) { - case BYTE: - buffer.put(((Number) value).byteValue()); - return; - case SHORT: - buffer.putShort(((Number) value).shortValue()); - return; - case INT: - buffer.putInt(((Number) value).intValue()); - return; - case LONG: - buffer.putLong(((Number) value).longValue()); - return; - case BYTE_ARRAY: - buffer.put((byte[]) value); - return; - case ADDRESS: - buffer.putInt(((MemoryLocation) value).address()); - return; - default: - // CHECKSTYLE:OFF - throw new Error("unreachable?"); - // CHECKSTYLE:ON + case BYTE -> buffer.put(((Number) value).byteValue()); + case SHORT -> buffer.putShort(((Number) value).shortValue()); + case INT -> buffer.putInt(((Number) value).intValue()); + case LONG -> buffer.putLong(((Number) value).longValue()); + case BYTE_ARRAY -> buffer.put((byte[]) value); + case ADDRESS -> buffer.putInt(((MemoryLocation) value).address()); + // CHECKSTYLE:OFF + default -> throw new Error("unreachable?"); + // CHECKSTYLE:ON } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java index 8f42b830c2..a0c1b234bb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/notification/NotificationMessage.java @@ -73,15 +73,12 @@ public void addToBuffer(ByteBuffer buffer) { * If the message is not understood. */ public static NotificationMessage build(ByteBuffer buffer) { - switch (NotificationMessageCode.get(buffer.getShort(0) & MAX_COMMAND)) { - case DATABASE_CONFIRMATION: - return new DatabaseConfirmation(buffer); - case START_RESUME_NOTIFICATION: - return new StartResume(buffer); - case STOP_PAUSE_NOTIFICATION: - return new PauseStop(buffer); - default: - throw new UnsupportedOperationException(); - } + return switch (NotificationMessageCode + .get(buffer.getShort(0) & MAX_COMMAND)) { + case DATABASE_CONFIRMATION -> new DatabaseConfirmation(buffer); + case START_RESUME_NOTIFICATION -> new StartResume(buffer); + case STOP_PAUSE_NOTIFICATION -> new PauseStop(buffer); + default -> throw new UnsupportedOperationException(); + }; } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillDataType.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillDataType.java index 7ca20a62ad..4275356d45 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillDataType.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillDataType.java @@ -23,11 +23,26 @@ */ public enum FillDataType { /** Fill by words (4 bytes). */ - WORD(4), + WORD(4) { + @Override + public void writeTo(int value, ByteBuffer buffer) { + buffer.putInt(value); + } + }, /** Fill by half words (2 bytes). */ - HALF_WORD(2), + HALF_WORD(2) { + @Override + public void writeTo(int value, ByteBuffer buffer) { + buffer.putShort((short) value); + } + }, /** Fill by single bytes. */ - BYTE(1); + BYTE(1) { + @Override + public void writeTo(int value, ByteBuffer buffer) { + buffer.put((byte) value); + } + }; /** The encoding of the fill unit size. */ public final int size; @@ -44,22 +59,5 @@ public enum FillDataType { * @param buffer * The buffer to write to. */ - public void writeTo(int value, ByteBuffer buffer) { - switch (this) { - case WORD: - buffer.putInt(value); - break; - case HALF_WORD: - buffer.putShort((short) value); - break; - case BYTE: - buffer.put((byte) value); - break; - default: - // unreachable - // CHECKSTYLE:OFF - throw new IllegalStateException(); - // CHECKSTYLE:ON - } - } + public abstract void writeTo(int value, ByteBuffer buffer); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java index 04d4216cbc..c4b2567adf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java @@ -71,8 +71,7 @@ private ProcessException(HasCoreLocation core, */ static ProcessException makeInstance(HasCoreLocation core, Throwable cause) throws InterruptedException { - if (requireNonNull( - cause) instanceof UnexpectedResponseCodeException urc) { + if (cause instanceof UnexpectedResponseCodeException urc) { if (urc.response == null) { return new ProcessException(core, cause, null); } @@ -114,7 +113,7 @@ static ProcessException makeInstance(HasCoreLocation core, if (cause instanceof InterruptedException interrupt) { throw interrupt; } - return new ProcessException(core, cause, null); + return new ProcessException(core, requireNonNull(cause), null); } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 70fe8672da..6d238ef82c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -724,25 +724,20 @@ private Object getSystemVariable(HasChipLocation chip, throws IOException, ProcessException, InterruptedException { var buffer = readMemory(chip, SYS_VARS.add(dataItem.offset), dataItem.type.value); - switch (dataItem.type) { - case BYTE: - return Byte.toUnsignedInt(buffer.get()); - case SHORT: - return Short.toUnsignedInt(buffer.getShort()); - case INT: - return buffer.getInt(); - case LONG: - return buffer.getLong(); - case BYTE_ARRAY: + return switch (dataItem.type) { + case BYTE -> Byte.toUnsignedInt(buffer.get()); + case SHORT -> Short.toUnsignedInt(buffer.getShort()); + case INT -> buffer.getInt(); + case LONG -> buffer.getLong(); + case BYTE_ARRAY -> { byte[] dst = (byte[]) dataItem.getDefault(); buffer.get(dst); - return dst; - case ADDRESS: - return new MemoryLocation(buffer.getInt()); - default: - // Unreachable - throw new IllegalStateException(); + yield dst; } + case ADDRESS -> new MemoryLocation(buffer.getInt()); + // Unreachable + default -> throw new IllegalStateException(); + }; } private ConnectionSelector bmpConnection(BMPCoords bmp) { diff --git a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java index cf0fa022bb..c9bcad9f10 100644 --- a/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java +++ b/SpiNNaker-data-specification/src/main/java/uk/ac/manchester/spinnaker/data_spec/Functions.java @@ -412,20 +412,11 @@ private void writeToMemory(long value, int dataLen, int numRepeats, var b = allocate(numRepeats * dataLen).order(LITTLE_ENDIAN); for (int i = 0; i < numRepeats; i++) { switch (dataLen) { - case 1: - b.put((byte) value); - break; - case 2: - b.putShort((short) value); - break; - case INT_SIZE: - b.putInt((int) value); - break; - case LONG_SIZE: - b.putLong(value); - break; - default: - throw new UnknownTypeLengthException(dataLen, command); + case 1 -> b.put((byte) value); + case 2 -> b.putShort((short) value); + case INT_SIZE -> b.putInt((int) value); + case LONG_SIZE -> b.putLong(value); + default -> throw new UnknownTypeLengthException(dataLen, command); } } writeToMemory(b.array(), command); diff --git a/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java b/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java index 5974ec900c..823c24788b 100644 --- a/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java +++ b/SpiNNaker-data-specification/src/test/java/uk/ac/manchester/spinnaker/data_spec/Generator.java @@ -120,66 +120,72 @@ enum Field { /** Types of values to write. */ public enum DataType { /** 8-bit integer. */ - INT8(1, LEN2), - /** 16-bit integer. */ - INT16(2, LEN2), - /** 32-bit integer. */ - INT32(4, LEN2), - /** 64-bit integer. */ - INT64(8, LEN3); - - private final int size; - - private final int writeLength; - - DataType(int size, int writeLength) { - this.size = size; - this.writeLength = writeLength; - } - - void putPacked(ByteBuffer buffer, Number n) { - switch (this) { - case INT8: + INT8(1, LEN2) { + @Override + void putPacked(ByteBuffer buffer, Number n) { buffer.put(n.byteValue()); - break; - case INT16: - buffer.putShort(n.shortValue()); - break; - case INT32: - buffer.putInt(n.intValue()); - break; - case INT64: - buffer.putLong(n.longValue()); - break; - default: - throw new UnsupportedOperationException(); } - } - void putPadded(ByteBuffer buffer, Number n) { - switch (this) { - case INT8: + @Override + void putPadded(ByteBuffer buffer, Number n) { buffer.put(n.byteValue()); // Add padding buffer.put((byte) 0); buffer.put((byte) 0); buffer.put((byte) 0); - break; - case INT16: + } + }, + /** 16-bit integer. */ + INT16(2, LEN2) { + @Override + void putPacked(ByteBuffer buffer, Number n) { + buffer.putShort(n.shortValue()); + } + + @Override + void putPadded(ByteBuffer buffer, Number n) { buffer.putShort(n.shortValue()); // Add padding buffer.putShort((short) 0); - break; - case INT32: + } + }, + /** 32-bit integer. */ + INT32(4, LEN2) { + @Override + void putPacked(ByteBuffer buffer, Number n) { + buffer.putInt(n.intValue()); + } + + @Override + void putPadded(ByteBuffer buffer, Number n) { buffer.putInt(n.intValue()); - break; - case INT64: + } + }, + /** 64-bit integer. */ + INT64(8, LEN3) { + @Override + void putPacked(ByteBuffer buffer, Number n) { + buffer.putLong(n.longValue()); + } + + @Override + void putPadded(ByteBuffer buffer, Number n) { buffer.putLong(n.longValue()); - break; - default: - throw new UnsupportedOperationException(); } + }; + + private final int size; + + private final int writeLength; + + DataType(int size, int writeLength) { + this.size = size; + this.writeLength = writeLength; } + + abstract void putPacked(ByteBuffer buffer, Number n); + + abstract void putPadded(ByteBuffer buffer, Number n); } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java index e80eee9df5..b1fa772d87 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java @@ -108,6 +108,7 @@ private static void wrongArgs(String cmd, String args) { * @param args * The command line arguments. */ + // TODO rewrite to use picocli? public static void main(String... args) { if (args.length < 1) { err.printf( @@ -183,7 +184,7 @@ public static void main(String... args) { case CLICommands.LISTEN: LocateConnectedMachineIPAddress.main(args); - return; + exit(0); case CLICommands.VERSION: System.out.println(VERSION); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java index 977ff550b7..fa710b9a63 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java @@ -54,7 +54,7 @@ public static void compareBuffers(ByteBuffer original, for (var delta : diff(list(original), list(downloaded)) .getDeltas()) { switch (delta.getType()) { - case CHANGE: + case CHANGE -> { var changeFrom = delta.getOriginal(); var changeTo = delta.getRevised(); log.warn( @@ -66,22 +66,19 @@ public static void compareBuffers(ByteBuffer original, changeTo.getPosition()); log.info("change {} -> {}", describeChunk(changeFrom), describeChunk(changeTo)); - break; - case DELETE: + } + case DELETE -> { var delete = delta.getOriginal(); log.warn("gather deleted {} bytes at {}", delete.getLines().size(), delete.getPosition()); log.info("delete {}", describeChunk(delete)); - break; - case INSERT: + } + default /* INSERT */ -> { var insert = delta.getRevised(); log.warn("gather inserted {} bytes at {}", insert.getLines().size(), insert.getPosition()); log.info("insert {}", describeChunk(insert)); - break; - default: - // Should be unreachable - break; + } } } break; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Direction.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Direction.java index 8ef0db4cc8..85d509bf7a 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Direction.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/Direction.java @@ -81,20 +81,14 @@ public enum Direction { * @return The inverse direction. */ Direction inverse() { - switch (this) { - case EAST: - return WEST; - case NORTHEAST: - return SOUTHWEST; - case NORTH: - return SOUTH; - case WEST: - return EAST; - case SOUTHWEST: - return NORTHEAST; - default: - return NORTH; - } + return switch (this) { + case EAST -> WEST; + case NORTHEAST -> SOUTHWEST; + case NORTH -> SOUTH; + case WEST -> EAST; + case SOUTHWEST -> NORTHEAST; + default -> NORTH; + }; } /** diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 063c204b2c..ad66bcb759 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -124,16 +124,13 @@ BMPCoords deserializeObject() throws IOException { String name; while ((name = getNextFieldName()) != null) { switch (name) { - case "cabinet": - case "c": + case "cabinet", "c" -> { c = requireSetOnceInt(name, c); - break; - case "frame": - case "f": + } + case "frame", "f" -> { f = requireSetOnceInt(name, f); - break; - default: - unknownProperty(name); + } + default -> unknownProperty(name); } } if (c == null || f == null) { diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java index 829e1f476c..9da761b0e2 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java @@ -48,17 +48,15 @@ public final T deserialize(JsonParser p, DeserializationContext ctxt) try { CONTEXT.set(ctxt); PARSER.set(p); - switch (p.currentToken()) { - case START_ARRAY: - return deserializeArray(); - case START_OBJECT: - return deserializeObject(); - case VALUE_STRING: - return deserializeString(p.getValueAsString()); - default: + return switch (p.currentToken()) { + case START_ARRAY -> deserializeArray(); + case START_OBJECT -> deserializeObject(); + case VALUE_STRING -> deserializeString(p.getValueAsString()); + default -> { ctxt.handleUnexpectedToken(_valueClass, p); - return null; + yield null; } + }; } finally { CONTEXT.remove(); PARSER.remove(); diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index b9ed6a0395..cd34480a13 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -141,20 +141,16 @@ PhysicalCoords deserializeObject() throws IOException { String name; while ((name = getNextFieldName()) != null) { switch (name) { - case "cabinet": - case "c": + case "cabinet", "c" -> { c = requireSetOnceInt(name, c); - break; - case "frame": - case "f": + } + case "frame", "f" -> { f = requireSetOnceInt(name, f); - break; - case "board": - case "b": + } + case "board", "b" -> { b = requireSetOnceInt(name, b); - break; - default: - unknownProperty(name); + } + default -> unknownProperty(name); } } if (c == null || f == null || b == null) { diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java index 0e33d929ec..f70b8e594d 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java @@ -165,10 +165,8 @@ private void startTransaction(Connection conn) throws SQLException { return; } catch (SQLiteException e) { switch (e.getResultCode()) { - case SQLITE_BUSY: - case SQLITE_BUSY_RECOVERY: - case SQLITE_BUSY_SNAPSHOT: - case SQLITE_BUSY_TIMEOUT: + case SQLITE_BUSY, SQLITE_BUSY_RECOVERY, SQLITE_BUSY_SNAPSHOT, + SQLITE_BUSY_TIMEOUT: if (log.isDebugEnabled()) { log.debug("database busy; trying to relock"); } From 218b69cbbad4a78738017839f83f85c8e31c434b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 4 Jan 2023 16:18:13 +0000 Subject: [PATCH 042/194] Work around internal bug in Error Prone 2.17.0 And use a somewhat cleaner way of writing the code where it blew up --- .../spinnaker/machine/board/BMPCoords.java | 19 +++++++------- .../machine/board/DeserializerHelper.java | 10 +++++++ .../machine/board/PhysicalCoords.java | 24 ++++++++--------- .../spinnaker/machine/board/TriadCoords.java | 26 ++++++++----------- .../spinnaker/utils/ValueHolder.java | 9 +++++++ pom.xml | 4 +++ 6 files changed, 54 insertions(+), 38 deletions(-) diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index ad66bcb759..6a87024b31 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -27,6 +27,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.errorprone.annotations.Immutable; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + /** * A simple description of a BMP to talk to. Supports equality and being used as * a hash key. @@ -120,23 +122,20 @@ BMPCoords deserializeArray() throws IOException { @Override BMPCoords deserializeObject() throws IOException { - Integer c = null, f = null; + ValueHolder c = new ValueHolder<>(), + f = new ValueHolder<>(); String name; while ((name = getNextFieldName()) != null) { switch (name) { - case "cabinet", "c" -> { - c = requireSetOnceInt(name, c); - } - case "frame", "f" -> { - f = requireSetOnceInt(name, f); - } + case "cabinet", "c" -> requireSetOnceInt(name, c); + case "frame", "f" -> requireSetOnceInt(name, f); default -> unknownProperty(name); } } - if (c == null || f == null) { - missingProperty("c", c, "f", f); + if (c.isEmpty() || f.isEmpty()) { + missingProperty("c", c.getValue(), "f", f.getValue()); } - return new BMPCoords(c, f); + return new BMPCoords(c.getValue(), f.getValue()); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java index 9da761b0e2..680fffaff1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java @@ -25,6 +25,8 @@ import com.google.errorprone.annotations.ForOverride; import com.google.errorprone.annotations.FormatMethod; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + /** * A helper class for JSON deserializers. * @@ -169,6 +171,14 @@ int requireSetOnceInt(String name, Integer current) throws IOException { return PARSER.get().nextIntValue(0); } + void requireSetOnceInt(String name, ValueHolder holder) + throws IOException { + if (!holder.isEmpty()) { + inputMismatch("Duplicate property '%s'", name); + } + holder.setValue(PARSER.get().nextIntValue(0)); + } + void missingProperty(String n1, Object v1) throws IOException { if (v1 == null) { inputMismatch("Missing required property '%s'", n1); diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index cd34480a13..12d4217f0b 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -29,6 +29,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.errorprone.annotations.Immutable; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + /** * Physical board coordinates. The {@code cabinet} and {@code frame} (with * multiple frames per cabinet) describe where a board is located within the @@ -137,26 +139,22 @@ PhysicalCoords deserializeArray() throws IOException { @Override PhysicalCoords deserializeObject() throws IOException { - Integer c = null, f = null, b = null; + ValueHolder c = new ValueHolder<>(), + f = new ValueHolder<>(), b = new ValueHolder<>(); String name; while ((name = getNextFieldName()) != null) { switch (name) { - case "cabinet", "c" -> { - c = requireSetOnceInt(name, c); - } - case "frame", "f" -> { - f = requireSetOnceInt(name, f); - } - case "board", "b" -> { - b = requireSetOnceInt(name, b); - } + case "cabinet", "c" -> requireSetOnceInt(name, c); + case "frame", "f" -> requireSetOnceInt(name, f); + case "board", "b" -> requireSetOnceInt(name, b); default -> unknownProperty(name); } } - if (c == null || f == null || b == null) { - missingProperty("c", c, "f", f, "b", b); + if (c.isEmpty() || f.isEmpty() || b.isEmpty()) { + missingProperty("c", c.getValue(), "f", f.getValue(), "b", + b.getValue()); } - return new PhysicalCoords(c, f, b); + return new PhysicalCoords(c.getValue(), f.getValue(), b.getValue()); } @Override diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index 7f7ae15379..3d7d243bd7 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -28,6 +28,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.utils.ValueHolder; /** * Triad coordinates. @@ -162,27 +163,22 @@ TriadCoords deserializeArray() throws IOException { @Override TriadCoords deserializeObject() throws IOException { - Integer x = null, y = null, z = null; + ValueHolder x = new ValueHolder<>(), + y = new ValueHolder<>(), z = new ValueHolder<>(); String name; while ((name = getNextFieldName()) != null) { switch (name) { - case "x": - x = requireSetOnceInt(name, x); - break; - case "y": - y = requireSetOnceInt(name, y); - break; - case "z": - z = requireSetOnceInt(name, z); - break; - default: - unknownProperty(name); + case "x" -> requireSetOnceInt(name, x); + case "y" -> requireSetOnceInt(name, y); + case "z" -> requireSetOnceInt(name, z); + default -> unknownProperty(name); } } - if (x == null || y == null || z == null) { - missingProperty("x", x, "y", y, "z", z); + if (x.isEmpty() || y.isEmpty() || z.isEmpty()) { + missingProperty("x", x.getValue(), "y", y.getValue(), "z", + z.getValue()); } - return new TriadCoords(x, y, z); + return new TriadCoords(x.getValue(), y.getValue(), z.getValue()); } @Override diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ValueHolder.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ValueHolder.java index 6211437692..1c7e54b04c 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ValueHolder.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ValueHolder.java @@ -45,6 +45,15 @@ public ValueHolder(T value) { this.value = value; } + /** + * Get whether a (non-{@code null}) value is absent. + * + * @return Whether a value is absent and this holder is empty. + */ + public boolean isEmpty() { + return value == null; + } + /** * Get the value held. * diff --git a/pom.xml b/pom.xml index 94f0cdde53..f1456e7e15 100644 --- a/pom.xml +++ b/pom.xml @@ -1014,6 +1014,8 @@ along with this program. If not, see . documentation for getters, and its suggested replacement is terrible. --> -Xep:MissingSummary:OFF + + -Xep:StatementSwitchToExpressionSwitch:OFF @@ -1042,6 +1044,8 @@ along with this program. If not, see . documentation for getters, and its suggested replacement is terrible. --> -Xep:MissingSummary:OFF + + -Xep:StatementSwitchToExpressionSwitch:OFF From 9d9ab5b0ed45985b7fd5485c33aded29986faf96 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 20 Jan 2023 17:16:53 +0000 Subject: [PATCH 043/194] indentfix --- .../ac/manchester/spinnaker/alloc/db/SQLQueries.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 dc29720aec..a3c14de915 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 @@ -2492,12 +2492,12 @@ JOIN boards USING (board_id) WHERE boards.functioning IS NOT 0 GROUP BY board_id) SELECT - boards.board_id, - report_counts.num_reports, - boards.x, - boards.y, - boards.z, - boards.address + boards.board_id, + report_counts.num_reports, + boards.x, + boards.y, + boards.z, + boards.address FROM report_counts JOIN boards USING (board_id) From 1f4fc5eb8455c7ad3b73d44d2b7139e26da6a390 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 26 Jan 2023 15:10:25 +0000 Subject: [PATCH 044/194] Neater instanceof usage --- .../uk/ac/manchester/spinnaker/alloc/allocator/Spalloc.java | 5 ++--- .../java/uk/ac/manchester/spinnaker/alloc/web/StubJob.java | 6 +----- .../uk/ac/manchester/spinnaker/alloc/web/StubMachine.java | 6 +----- 3 files changed, 4 insertions(+), 13 deletions(-) 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 f0604b9086..6b4a7c807e 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 @@ -921,8 +921,7 @@ public List getBoardNumbers(BMPCoords bmp) { @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 @@ -1463,7 +1462,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 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 8ca7f57c56..72b04aa090 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 @@ -142,11 +142,7 @@ public void forgetProxy(ProxyCore proxy) { @Override public final boolean equals(Object other) { - if (other instanceof Job) { - Job 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 f39b2757f9..c49239d0e2 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 @@ -130,11 +130,7 @@ public List getBoardNumbers(BMPCoords bmp) { @Override public final boolean equals(Object other) { - if (other instanceof Machine) { - Machine m = (Machine) other; - return getId() == m.getId(); - } - return false; + return (other instanceof Machine m) && (getId() == m.getId()); } @Override From e3a711620e99141fd8bf80f024cfe9208464c693 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 31 Jan 2023 14:57:31 +0000 Subject: [PATCH 045/194] Fix codeql scan (merge was wrong) --- .github/workflows/codeql-analysis.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8c2f354232..0d0ab246ed 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,18 +47,12 @@ jobs: # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - version: [ 11 ] + version: [ 17 ] steps: - name: Checkout repository uses: actions/checkout@v3 - # CodeQL defaults to wrong version without this. - - name: Initialize Java - uses: actions/setup-java@v1 - with: - java-version: 17 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 @@ -70,7 +64,8 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main # Set up right Java version: https://github.com/github/codeql-action/issues/825 - - uses: actions/setup-java@v3.6.0 + - name: Initialize Java ${{ matrix.version }} + uses: actions/setup-java@v3.6.0 with: java-version: ${{ matrix.version }} distribution: zulu From 60989e60c3579d675d16580a05200a3b8256f242 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 9 Feb 2023 11:58:33 +0000 Subject: [PATCH 046/194] Missed two files --- .../spalloc/messages/CustomIntCommand.java | 19 +++++++++---------- .../spalloc/messages/CustomStringCommand.java | 19 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java index 1404b8c688..ad1549fe8e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomIntCommand.java @@ -1,18 +1,17 @@ /* * Copyright (c) 2018 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.spalloc.messages; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java index a46573f86b..a47c333845 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/CustomStringCommand.java @@ -1,18 +1,17 @@ /* * Copyright (c) 2018 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.spalloc.messages; From 93a151e0a3cf8ee6a8a9efd5390678d64c5270db Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 9 Feb 2023 12:01:19 +0000 Subject: [PATCH 047/194] And one more --- .../spinnaker/front_end/DebuggingUtils.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java index fa710b9a63..39f43a99ed 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java @@ -1,18 +1,17 @@ /* * Copyright (c) 2019-2022 The University of Manchester * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.front_end; From b168284ab9954386e156be0454dc36671a60a8c5 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 10 Feb 2023 11:26:14 +0000 Subject: [PATCH 048/194] Fix a few new places to follow the language profile --- .../ac/manchester/spinnaker/messages/scp/ClearIOBUF.java | 2 +- .../spinnaker/messages/scp/ClearReinjectionQueue.java | 3 ++- .../ac/manchester/spinnaker/messages/scp/FECRequest.java | 5 +++-- .../spinnaker/messages/scp/GetReinjectionStatus.java | 2 +- .../spinnaker/messages/scp/ReinjectorRequest.java | 8 +++++--- .../spinnaker/messages/scp/ResetReinjectionCounters.java | 3 ++- .../spinnaker/messages/scp/RouterTableRequest.java | 5 +++-- .../spinnaker/messages/scp/SetReinjectionPacketTypes.java | 2 +- .../spinnaker/messages/scp/SetRouterEmergencyTimeout.java | 2 +- .../spinnaker/messages/scp/SetRouterTimeout.java | 2 +- .../spinnaker/messages/scp/UpdateProvenanceAndExit.java | 2 +- .../manchester/spinnaker/messages/scp/UpdateRuntime.java | 2 +- .../ac/manchester/spinnaker/transceiver/TxrxProcess.java | 3 +-- 13 files changed, 23 insertions(+), 18 deletions(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearIOBUF.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearIOBUF.java index 3b1cfe0455..95c46791f3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearIOBUF.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearIOBUF.java @@ -28,7 +28,7 @@ * This calls {@code sark_io_buf_reset()} in {@code sark_io.c} (via * {@code simulation_control_scp_callback()} in {@code simulation.c}). */ -public class ClearIOBUF extends FECRequest { +public final class ClearIOBUF extends FECRequest { /** * @param core * The core to clear the IOBUF of. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearReinjectionQueue.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearReinjectionQueue.java index e543d4f9bc..ebebb41f74 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearReinjectionQueue.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ClearReinjectionQueue.java @@ -28,7 +28,8 @@ *

* Handled by {@code reinjection_clear()} in {@code extra_monitor_support.c}. */ -public class ClearReinjectionQueue extends ReinjectorRequest { +public final class ClearReinjectionQueue + extends ReinjectorRequest { /** * @param core * The coordinates of the monitor core. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java index 1ae9add233..8997be7c3d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java @@ -30,8 +30,9 @@ * @param * The type of response expected. */ -// TODO Seal in 17 -public abstract class FECRequest extends SCPRequest { +public abstract sealed class FECRequest + extends SCPRequest< + T> permits ClearIOBUF, UpdateProvenanceAndExit, UpdateRuntime { /** * @param core * Where to send the request. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetReinjectionStatus.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetReinjectionStatus.java index eabea1e03c..7c68b2eb75 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetReinjectionStatus.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetReinjectionStatus.java @@ -30,7 +30,7 @@ * Handled by {@code reinjection_get_status()} in * {@code extra_monitor_support.c}. */ -public class GetReinjectionStatus +public final class GetReinjectionStatus extends ReinjectorRequest { /** * @param core diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java index 83ce71e41c..a1164e215a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java @@ -30,9 +30,11 @@ * @param * The type of response. */ -//TODO Seal in 17 -public abstract class ReinjectorRequest - extends SCPRequest { +public abstract sealed class ReinjectorRequest + extends SCPRequest + permits ClearReinjectionQueue, GetReinjectionStatus, + ResetReinjectionCounters, SetReinjectionPacketTypes, + SetRouterEmergencyTimeout, SetRouterTimeout { /** * @param core * Where to send the request. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ResetReinjectionCounters.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ResetReinjectionCounters.java index ec6f076a86..f7709405af 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ResetReinjectionCounters.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ResetReinjectionCounters.java @@ -29,7 +29,8 @@ * Handled by {@code reinjection_reset_counters()} in * {@code extra_monitor_support.c}. */ -public class ResetReinjectionCounters extends ReinjectorRequest { +public final class ResetReinjectionCounters + extends ReinjectorRequest { /** * @param core * The coordinates of the monitor core. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java index efc7c26df6..5fb1ef0da3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java @@ -30,8 +30,9 @@ * A command message to an extra monitor control core to manipulate the router * table. */ -//TODO Seal in 17 -public abstract class RouterTableRequest extends SCPRequest { +public abstract sealed class RouterTableRequest + extends SCPRequest + permits LoadApplicationRoutes, LoadSystemRoutes, SaveApplicationRoutes { private final RouterTableCommand cmd; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetReinjectionPacketTypes.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetReinjectionPacketTypes.java index dda7a90ec2..4165cc60d8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetReinjectionPacketTypes.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetReinjectionPacketTypes.java @@ -30,7 +30,7 @@ * Handled by {@code reinjection_set_packet_types()} in * {@code extra_monitor_support.c}. */ -public class SetReinjectionPacketTypes +public final class SetReinjectionPacketTypes extends ReinjectorRequest { /** * @param core diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterEmergencyTimeout.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterEmergencyTimeout.java index fa5a46a667..e617f33e05 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterEmergencyTimeout.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterEmergencyTimeout.java @@ -30,7 +30,7 @@ * Handled by {@code reinjection_set_emergency_timeout_sdp()} in * {@code extra_monitor_support.c}. */ -public class SetRouterEmergencyTimeout +public final class SetRouterEmergencyTimeout extends ReinjectorRequest { /** * @param core diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterTimeout.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterTimeout.java index 259c91bb7d..7f3ff45c74 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterTimeout.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetRouterTimeout.java @@ -30,7 +30,7 @@ * Handled by {@code reinjection_set_timeout_sdp()} in * {@code extra_monitor_support.c}. */ -public class SetRouterTimeout extends ReinjectorRequest { +public final class SetRouterTimeout extends ReinjectorRequest { /** * @param core * The coordinates of the monitor core. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateProvenanceAndExit.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateProvenanceAndExit.java index 4e89083915..f3c6feb1f2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateProvenanceAndExit.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateProvenanceAndExit.java @@ -29,7 +29,7 @@ *

* This calls {@code simulation_control_scp_callback()} in {@code simulation.c}. */ -public class UpdateProvenanceAndExit extends FECRequest { +public final class UpdateProvenanceAndExit extends FECRequest { /** * @param core * The SpiNNaker core to update the provenance info of. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateRuntime.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateRuntime.java index 976cbe7013..71698fe6a1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateRuntime.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/UpdateRuntime.java @@ -28,7 +28,7 @@ *

* This calls {@code simulation_control_scp_callback()} in {@code simulation.c}. */ -public class UpdateRuntime extends FECRequest { +public final class UpdateRuntime extends FECRequest { /** * @param core * The SpiNNaker core to update the runtime info of. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java index f73ce3f20f..d8ae8940ca 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java @@ -718,8 +718,7 @@ void send(SCPRequest request, */ private Request registerRequest( SCPRequest request, Consumer callback) { - if (request instanceof ConnectionAwareMessage) { - ConnectionAwareMessage cam = (ConnectionAwareMessage) request; + if (request instanceof ConnectionAwareMessage cam) { cam.setConnection(connection); } synchronized (outstandingRequests) { From 5d47b2d0a59d00620b96962b2d803672a49498ed Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 10 Feb 2023 11:42:57 +0000 Subject: [PATCH 049/194] Convert SerialVector to record --- .../messages/bmp/ReadSerialVector.java | 14 +++- .../spinnaker/messages/bmp/SerialVector.java | 75 +++++-------------- .../spinnaker/transceiver/Transceiver.java | 11 +-- 3 files changed, 35 insertions(+), 65 deletions(-) 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 ca79b3d95c..5a831eba14 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,10 +16,13 @@ package uk.ac.manchester.spinnaker.messages.bmp; import static uk.ac.manchester.spinnaker.messages.bmp.BMPInfo.SERIAL; +import static uk.ac.manchester.spinnaker.messages.bmp.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.UnexpectedResponseCodeException; @@ -54,7 +57,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/SerialVector.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java index 98849f8953..3dc11844fb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java @@ -15,7 +15,6 @@ */ package uk.ac.manchester.spinnaker.messages.bmp; -import java.nio.ByteBuffer; import java.nio.IntBuffer; import uk.ac.manchester.spinnaker.machine.MemoryLocation; @@ -28,50 +27,30 @@ *

* See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. * + * @param hardwareVersion + * Hardware version. + * @param serialNumber + * LPC1768 serial number. Length {@value #SERIAL_LENGTH}. + * @param flashBuffer + * Flash buffer address. + * @param boardStat + * {@code board_stat} address for the board. See {@link ReadADC} for + * an operation that reads this. + * @param cortexBoot + * Cortex boot vector address. Can be used to determine which copy of + * the BMP code was successfully booted from. * @see ReadSerialVector */ @UsedInJavadocOnly(SCPCommand.class) -public class SerialVector { +public record SerialVector(int hardwareVersion, IntBuffer serialNumber, + MemoryLocation flashBuffer, MemoryLocation boardStat, + MemoryLocation cortexBoot) { /** The number of words in the {@link #getSerialNumber() serial_number}. */ public static final int SERIAL_LENGTH = 4; - /** Hardware version. */ - private final int hardwareVersion; - - /** LPC1768 serial number. Length 4. */ - private final IntBuffer serialNumber; - - /** Flash buffer address. */ - private final MemoryLocation flashBuffer; - - /** {@code board_stat} address for the board. */ - private final MemoryLocation boardStat; - - /** Cortex boot vector address. */ - private final MemoryLocation cortexBoot; - /** - * @param buffer - * Where to deserialize the vector from. - */ - SerialVector(ByteBuffer buffer) { - var b = buffer.asIntBuffer(); - hardwareVersion = b.get(); - var sn = new int[SERIAL_LENGTH]; - b.get(sn); - serialNumber = IntBuffer.wrap(sn); - flashBuffer = new MemoryLocation(b.get()); - boardStat = new MemoryLocation(b.get()); - cortexBoot = new MemoryLocation(b.get()); - } - - /** @return The hardware version. */ - public int getHardwareVersion() { - return hardwareVersion; - } - - /** - * @return The device serial number, as a read-only buffer. + * @return The device serial number, as a read-only buffer. Length + * {@value #SERIAL_LENGTH}. */ // @formatter:off /* Obtained from LPC17xx In Application Programming function 58. The API @@ -94,26 +73,8 @@ public int getHardwareVersion() { * The four words of the result form the four words provided below, in the * order described above (not that that typically matters). */ // @formatter:on - public IntBuffer getSerialNumber() { + public IntBuffer serialNumber() { // Make a new instance so positions aren't shared return serialNumber.asReadOnlyBuffer(); } - - /** @return The location of the flash buffer. */ - public MemoryLocation getFlashBuffer() { - return flashBuffer; - } - - /** - * @return The board status block location. - * @see ReadADC - */ - public MemoryLocation getBoardStatusLocation() { - return boardStat; - } - - /** @return The location of the Cortex boot vector. */ - public MemoryLocation getCortexVector() { - return cortexBoot; - } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 3387f11c24..345cc11ba3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -38,7 +38,6 @@ import static uk.ac.manchester.spinnaker.messages.Constants.SCP_SCAMP_PORT; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_BOOT_CONNECTION_DEFAULT_PORT; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; -import static uk.ac.manchester.spinnaker.messages.bmp.SerialVector.SERIAL_LENGTH; import static uk.ac.manchester.spinnaker.messages.bmp.WriteFlashBuffer.FLASH_CHUNK_SIZE; import static uk.ac.manchester.spinnaker.messages.model.IPTagTimeOutWaitTime.TIMEOUT_2560_ms; import static uk.ac.manchester.spinnaker.messages.model.PowerCommand.POWER_OFF; @@ -1877,17 +1876,15 @@ public void writeBMPMemory(BMPCoords bmp, BMPBoard board, @Override public MemoryLocation getSerialFlashBuffer(BMPCoords bmp, BMPBoard board) throws IOException, ProcessException, InterruptedException { - return get(bmp, new ReadSerialVector(board)).getFlashBuffer(); + return get(bmp, new ReadSerialVector(board)).flashBuffer(); } @Override public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) throws IOException, ProcessException, InterruptedException { - var serialNumber = new int[SERIAL_LENGTH]; - get(bmp, new ReadSerialVector(board)).getSerialNumber() - .get(serialNumber); - return format("%08x-%08x-%08x-%08x", - stream(serialNumber).mapToObj(Integer::valueOf).toArray()); + var sn = get(bmp, new ReadSerialVector(board)).serialNumber(); + return format("%08x-%08x-%08x-%08x", // + sn.get(), sn.get(), sn.get(), sn.get()); } @Override From 885fb5e8ce8e88be69668707aaa12b712e8e23c1 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 10 Feb 2023 11:52:15 +0000 Subject: [PATCH 050/194] Shuffle some classes around --- .../bmp/{BMPReadMemory.java => ReadBMPMemory.java} | 4 ++-- .../spinnaker/messages/bmp/ReadSerialVector.java | 3 ++- .../bmp/{BMPSetLED.java => SetBoardLEDs.java} | 4 ++-- .../{BMPWriteMemory.java => WriteBMPMemory.java} | 4 ++-- .../messages/{bmp => model}/SerialVector.java | 10 ++++------ .../transceiver/BMPReadMemoryProcess.java | 4 ++-- .../transceiver/BMPWriteMemoryProcess.java | 10 +++++----- .../spinnaker/transceiver/Transceiver.java | 4 ++-- .../spinnaker/messages/scp/GeneralMessageTest.java | 14 +++++++------- 9 files changed, 28 insertions(+), 29 deletions(-) rename SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/{BMPReadMemory.java => ReadBMPMemory.java} (95%) rename SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/{BMPSetLED.java => SetBoardLEDs.java} (93%) rename SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/{BMPWriteMemory.java => WriteBMPMemory.java} (93%) rename SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/{bmp => model}/SerialVector.java (87%) 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 95% 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 9fc1728ffe..8e8f9a4f75 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 @@ -32,7 +32,7 @@ *

* Calls {@code cmd_read()} in {@code bmp_cmd.c}. */ -public class BMPReadMemory extends BMPRequest { +public class ReadBMPMemory extends BMPRequest { private static int validate(int size) { if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) { throw new IllegalArgumentException( @@ -49,7 +49,7 @@ 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) { + public ReadBMPMemory(BMPBoard board, MemoryLocation address, int size) { super(board, CMD_READ, address.address(), validate(size), efficientTransferUnit(address, size).value); } 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 5a831eba14..a6c74c3c43 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,7 +16,7 @@ package uk.ac.manchester.spinnaker.messages.bmp; import static uk.ac.manchester.spinnaker.messages.bmp.BMPInfo.SERIAL; -import static uk.ac.manchester.spinnaker.messages.bmp.SerialVector.SERIAL_LENGTH; +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; @@ -24,6 +24,7 @@ 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; /** 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 93% 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 7a53783a55..14e04bee03 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 @@ -28,7 +28,7 @@ *

* Handled by {@code cmp_led()} in {@code bmp_cmd.c}. */ -public class BMPSetLED extends BMPRequest { +public class SetBoardLEDs extends BMPRequest { /** * Make a request. * @@ -39,7 +39,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)); } 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 93% 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 6e7b9b21dc..b300d21b59 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 class WriteBMPMemory extends BMPRequest { /** * @param board * the board with the BMP to write the memory of @@ -40,7 +40,7 @@ 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(), efficientTransferUnit(baseAddress, data.remaining()).value, diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java similarity index 87% rename from SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java rename to SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java index 3dc11844fb..4960d49c48 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.ac.manchester.spinnaker.messages.bmp; +package uk.ac.manchester.spinnaker.messages.model; import java.nio.IntBuffer; import uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.messages.scp.SCPCommand; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; +import uk.ac.manchester.spinnaker.messages.bmp.ReadADC; +import uk.ac.manchester.spinnaker.messages.bmp.ReadSerialVector; /** - * The data in the serial vector. The result of a {@link SCPCommand#CMD_BMP_INFO - * BMP_INFO} call with argument {@link BMPInfo#SERIAL SERIAL}. + * The data in the BMP serial vector. *

* See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. * @@ -41,7 +40,6 @@ * the BMP code was successfully booted from. * @see ReadSerialVector */ -@UsedInJavadocOnly(SCPCommand.class) public record SerialVector(int hardwareVersion, IntBuffer serialNumber, MemoryLocation flashBuffer, MemoryLocation boardStat, MemoryLocation cortexBoot) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPReadMemoryProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPReadMemoryProcess.java index 88490593cc..9509ad4102 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPReadMemoryProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPReadMemoryProcess.java @@ -27,7 +27,7 @@ import uk.ac.manchester.spinnaker.connections.ConnectionSelector; import uk.ac.manchester.spinnaker.machine.MemoryLocation; import uk.ac.manchester.spinnaker.machine.board.BMPBoard; -import uk.ac.manchester.spinnaker.messages.bmp.BMPReadMemory; +import uk.ac.manchester.spinnaker.messages.bmp.ReadBMPMemory; import uk.ac.manchester.spinnaker.transceiver.Accumulator.BufferAccumulator; import uk.ac.manchester.spinnaker.transceiver.Accumulator.FileAccumulator; @@ -73,7 +73,7 @@ private T read(BMPBoard board, MemoryLocation address, int size, for (int offset = 0, chunk; offset < size; offset += chunk) { chunk = min(size - offset, UDP_MESSAGE_MAX_SIZE); accum.add(offset, - call(new BMPReadMemory(board, address.add(offset), chunk))); + call(new ReadBMPMemory(board, address.add(offset), chunk))); } return accum.finish(); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java index 47f81dae04..142025000d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPWriteMemoryProcess.java @@ -31,7 +31,7 @@ import uk.ac.manchester.spinnaker.machine.MemoryLocation; import uk.ac.manchester.spinnaker.machine.board.BMPBoard; import uk.ac.manchester.spinnaker.messages.Constants; -import uk.ac.manchester.spinnaker.messages.bmp.BMPWriteMemory; +import uk.ac.manchester.spinnaker.messages.bmp.WriteBMPMemory; import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; import uk.ac.manchester.spinnaker.utils.ValueHolder; @@ -137,7 +137,7 @@ ByteBuffer prepareSendBuffer(int chunkSize) { * * @author Donal Fellows */ -abstract class BMPWriteIterator implements Iterable { +abstract class BMPWriteIterator implements Iterable { private final BMPBoard board; private int sizeRemaining; @@ -172,7 +172,7 @@ abstract class BMPWriteIterator implements Iterable { abstract ByteBuffer prepareSendBuffer(int plannedSize); @Override - public Iterator iterator() { + public Iterator iterator() { return new Iterator<>() { @Override public boolean hasNext() { @@ -185,10 +185,10 @@ public boolean hasNext() { } @Override - public BMPWriteMemory next() { + public WriteBMPMemory next() { int chunkSize = sendBuffer.remaining(); try { - return new BMPWriteMemory(board, address, sendBuffer); + return new WriteBMPMemory(board, address, sendBuffer); } finally { address = address.add(chunkSize); sizeRemaining -= chunkSize; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java index 345cc11ba3..8730099a28 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Transceiver.java @@ -113,7 +113,7 @@ import uk.ac.manchester.spinnaker.machine.tags.ReverseIPTag; import uk.ac.manchester.spinnaker.machine.tags.Tag; import uk.ac.manchester.spinnaker.messages.bmp.BMPRequest; -import uk.ac.manchester.spinnaker.messages.bmp.BMPSetLED; +import uk.ac.manchester.spinnaker.messages.bmp.SetBoardLEDs; import uk.ac.manchester.spinnaker.messages.bmp.EraseFlash; import uk.ac.manchester.spinnaker.messages.bmp.GetBMPVersion; import uk.ac.manchester.spinnaker.messages.bmp.GetFPGAResetStatus; @@ -1808,7 +1808,7 @@ public void power(PowerCommand powerCommand, BMPCoords bmp, public void setLED(Collection leds, LEDAction action, BMPCoords bmp, Collection board) throws IOException, ProcessException, InterruptedException { - call(bmp, new BMPSetLED(leds, action, board)); + call(bmp, new SetBoardLEDs(leds, action, board)); } @Override diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/GeneralMessageTest.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/GeneralMessageTest.java index a6c202f579..86d90bac5f 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/GeneralMessageTest.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/GeneralMessageTest.java @@ -39,9 +39,9 @@ import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.board.BMPBoard; -import uk.ac.manchester.spinnaker.messages.bmp.BMPReadMemory; -import uk.ac.manchester.spinnaker.messages.bmp.BMPSetLED; -import uk.ac.manchester.spinnaker.messages.bmp.BMPWriteMemory; +import uk.ac.manchester.spinnaker.messages.bmp.ReadBMPMemory; +import uk.ac.manchester.spinnaker.messages.bmp.SetBoardLEDs; +import uk.ac.manchester.spinnaker.messages.bmp.WriteBMPMemory; import uk.ac.manchester.spinnaker.messages.bmp.EraseFlash; import uk.ac.manchester.spinnaker.messages.bmp.GetBMPVersion; import uk.ac.manchester.spinnaker.messages.bmp.GetFPGAResetStatus; @@ -369,19 +369,19 @@ void writeMemory() { class Bmp { @Test void readMemory() { - assertEquals(NO_PAYLOAD, length(new BMPReadMemory(BOARD, NULL, 4))); + assertEquals(NO_PAYLOAD, length(new ReadBMPMemory(BOARD, NULL, 4))); } @Test - void setLed() { + void setBoardLeds() { assertEquals(NO_PAYLOAD, - length(new BMPSetLED(asList(0), TOGGLE, asList(BOARD)))); + length(new SetBoardLEDs(asList(0), TOGGLE, asList(BOARD)))); } @Test void writeMemory() { var b = allocate(128); - assertEquals(152, length(new BMPWriteMemory(BOARD, NULL, b))); + assertEquals(152, length(new WriteBMPMemory(BOARD, NULL, b))); } @Test From 8880abc2c040880cb779b4cfa2c551ed87d15ef5 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 10 Feb 2023 12:22:49 +0000 Subject: [PATCH 051/194] More new style switch, mark some model classes as Java Beans --- .../spinnaker/alloc/model/BoardRecord.java | 3 +- .../spinnaker/alloc/model/GroupRecord.java | 1 + .../spinnaker/alloc/model/JavaBean.java | 40 +++++++++++++++++++ .../spinnaker/alloc/model/JobDescription.java | 1 + .../alloc/model/JobListEntryRecord.java | 1 + .../alloc/model/MachineDescription.java | 1 + .../alloc/model/MachineListEntryRecord.java | 1 + .../spinnaker/alloc/model/MachineTagging.java | 1 + .../spinnaker/alloc/model/MemberRecord.java | 1 + .../alloc/model/PasswordChangeRecord.java | 1 + .../spinnaker/alloc/model/UserRecord.java | 1 + .../connections/model/SCPSenderReceiver.java | 7 +--- .../messages/eieio/EIEIODataMessage.java | 15 ++++--- .../model/SystemVariableDefinition.java | 23 +++++------ .../spinnaker/messages/scp/SCPResponse.java | 3 +- .../spinnaker/spalloc/SpallocJob.java | 2 +- .../spinnaker/transceiver/TxrxProcess.java | 7 +--- .../spinnaker/machine/board/TriadCoords.java | 13 +++--- .../sqlite/SQLiteConnectionManager.java | 11 ++--- .../storage/sqlite/SQLiteProxyStorage.java | 14 +++---- 20 files changed, 93 insertions(+), 54 deletions(-) create mode 100644 SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/JavaBean.java 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 06b250689f..e429328007 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 @@ -39,9 +39,8 @@ * * @author Donal Fellows */ +@JavaBean public class BoardRecord { - // This class is visible to JSTL expressions; it MUST be a bean - // TODO convert to structured form private Integer id; @NotBlank 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 7b668b8f62..7840cd53f9 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 @@ -35,6 +35,7 @@ * 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..e46450cef7 --- /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 + * + * http://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 47626cdc91..fa13815b78 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 @@ -54,6 +54,7 @@ * * (That's actually slightly edited output from {@code spalloc-job -info}) */ +@JavaBean public class JobDescription { private int id; 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 d95d7f3b92..59478ee31e 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 @@ -70,6 +70,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 1246af37ca..a60718ff93 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 @@ -32,6 +32,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 2ba828635b..5b9696f33e 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 @@ -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 c23863a7ba..bc96c54ef1 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 @@ -36,6 +36,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 9d01da34e8..f4fbb541fa 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 @@ -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 608ba60973..6809f5734d 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 @@ -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/UserRecord.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/UserRecord.java index 6d80a4c26f..27b9f2a5ff 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 @@ -46,6 +46,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-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 c13ce5fe3d..d898c74031 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/eieio/EIEIODataMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java index 741b54dd73..4872141211 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java @@ -20,6 +20,7 @@ import static java.lang.Short.toUnsignedInt; import static java.lang.String.format; import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static java.util.Collections.emptyIterator; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; import static uk.ac.manchester.spinnaker.messages.eieio.EIEIOPrefix.LOWER_HALF_WORD; import static uk.ac.manchester.spinnaker.transceiver.Utils.newMessageBuffer; @@ -36,7 +37,8 @@ * @author Sergio Davies * @author Donal Fellows */ -public class EIEIODataMessage implements EIEIOMessage, +public final class EIEIODataMessage + implements EIEIOMessage, MappableIterable { private final Header header; @@ -198,19 +200,22 @@ public void addToBuffer(ByteBuffer buffer) { @Override public Iterator iterator() { - final var d = - data == null ? null : data.duplicate().order(LITTLE_ENDIAN); + if (data == null) { + return emptyIterator(); + } + + final var d = data.duplicate().order(LITTLE_ENDIAN); return new Iterator() { private int elementsRead = 0; @Override public boolean hasNext() { - return d != null && elementsRead < header.getCount(); + return elementsRead < header.getCount(); } @Override public AbstractDataElement next() { - if (d == null || !hasNext()) { + if (!hasNext()) { throw new NoSuchElementException("read all elements"); } elementsRead++; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java index 0950f3773f..48345807b5 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SystemVariableDefinition.java @@ -265,19 +265,16 @@ public Object getDefault() { this.type = type; this.offset = offset; hasDefinedDefault = true; - switch (type) { - case ADDRESS: - this.defAddr = new MemoryLocation(((Number) def).intValue()); - this.def = 0; - break; - case BYTE_ARRAY: - this.defAddr = NULL; - this.def = 0; - break; - default: - this.defAddr = NULL; - this.def = ((Number) def).intValue(); - } + + this.def = switch (type) { + case ADDRESS, BYTE_ARRAY -> 0; + default -> ((Number) def).intValue(); + }; + + defAddr = switch (type) { + case ADDRESS -> new MemoryLocation(((Number) def).intValue()); + default -> NULL; + }; } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SCPResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SCPResponse.java index 2d353fc9d6..1eb605de3b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SCPResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SCPResponse.java @@ -71,8 +71,7 @@ protected final void throwIfNotOK(String operation, Enum command) case RC_OK: return; case RC_ROUTE: - throw new UnroutableMessageException(operation, command, - sdpHeader); + throw new UnroutableMessageException(operation, command, sdpHeader); default: throw new UnexpectedResponseCodeException(operation, command, result); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java index 559617e1eb..b4ae045cec 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJob.java @@ -883,7 +883,7 @@ public void waitUntilReady(Integer timeout) switch (curState) { case READY: log.info("job:{} is now ready", id); - // Now in the ready state! + // Now in the ready state! Done successfully. return; case QUEUED: log.info("job:{} has been queued by the spalloc server", id); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java index d8ae8940ca..946bcdea4c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java @@ -556,12 +556,9 @@ public void send() throws IOException { "interrupted while waiting to send"); } switch (request.sdpHeader.getFlags()) { - case REPLY_EXPECTED: - case REPLY_EXPECTED_NO_P2P: + case REPLY_EXPECTED, REPLY_EXPECTED_NO_P2P -> connection.send(requestData, seq); - break; - default: - connection.send(requestData); + default -> connection.send(requestData); } nextSendTime = nanoTime() + INTER_SEND_INTERVAL_NS; } diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index 21a29febe2..89bde313d7 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -110,17 +110,16 @@ public ChipLocation asChipLocation() { int rootX = x * TRIAD_CHIP_SIZE; int rootY = y * TRIAD_CHIP_SIZE; switch (z) { - case 1: + case 1 -> { rootX += TRIAD_MAJOR_OFFSET; rootY += TRIAD_MINOR_OFFSET; - break; - case 2: + } + case 2 -> { rootX += TRIAD_MINOR_OFFSET; rootY += TRIAD_MAJOR_OFFSET; - break; - case 0: - default: - break; + } + default -> { + } } return new ChipLocation(rootX, rootY); } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java index 5b63be3c3d..21d967c0d6 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java @@ -165,14 +165,11 @@ private void startTransaction(Connection conn) throws SQLException { } catch (SQLiteException e) { switch (e.getResultCode()) { case SQLITE_BUSY, SQLITE_BUSY_RECOVERY, SQLITE_BUSY_SNAPSHOT, - SQLITE_BUSY_TIMEOUT: - if (log.isDebugEnabled()) { - log.debug("database busy; trying to relock"); - } + SQLITE_BUSY_TIMEOUT -> { + log.debug("database busy; trying to relock"); code = e.getResultCode(); - continue; - default: - throw e; + } + default -> throw e; } } } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java index a13309f4b6..73aa7bd706 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java @@ -68,20 +68,20 @@ private ProxyInformation getProxyInfo(Connection conn) throws SQLException { continue; } switch (name) { - case SPALLOC_URI: + case SPALLOC_URI -> { spallocUri = value; - break; - case PROXY_URI: + } + case PROXY_URI -> { jobUri = value; - break; - case PROXY_AUTH: + } + case PROXY_AUTH -> { if (!value.startsWith(PREFIX)) { throw new SQLException( "Unexpected proxy authentication: " + value); } bearerToken = value.substring(PREFIX.length()); - break; - default: + } + default -> throw new IllegalStateException("unreachable reached"); } } From b16cffb5d5a4dd4790efb2122364036107a9b353 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 13 Feb 2023 08:57:30 +0000 Subject: [PATCH 052/194] Message classes should be final --- .../spinnaker/alloc/client/BriefMachineDescription.java | 2 +- .../java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java | 2 +- .../uk/ac/manchester/spinnaker/alloc/client/Machines.java | 2 +- .../java/uk/ac/manchester/spinnaker/alloc/client/Power.java | 2 +- .../uk/ac/manchester/spinnaker/alloc/client/RootInfo.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java | 2 +- .../manchester/spinnaker/messages/bmp/GetFPGAResetStatus.java | 2 +- .../uk/ac/manchester/spinnaker/messages/bmp/InitFPGA.java | 2 +- .../java/uk/ac/manchester/spinnaker/messages/bmp/ReadADC.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/ReadCANStatus.java | 2 +- .../manchester/spinnaker/messages/bmp/ReadFPGARegister.java | 3 ++- .../ac/manchester/spinnaker/messages/bmp/ReadIPAddress.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java | 3 ++- .../manchester/spinnaker/messages/bmp/ReadSerialFlashCRC.java | 2 +- .../manchester/spinnaker/messages/bmp/ReadSerialVector.java | 3 ++- .../uk/ac/manchester/spinnaker/messages/bmp/ResetFPGA.java | 2 +- .../uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.java | 2 +- .../uk/ac/manchester/spinnaker/messages/bmp/SetPower.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java | 2 +- .../ac/manchester/spinnaker/messages/bmp/WriteFPGAData.java | 2 +- .../manchester/spinnaker/messages/bmp/WriteFPGARegister.java | 3 ++- .../manchester/spinnaker/messages/bmp/WriteFlashBuffer.java | 2 +- .../manchester/spinnaker/messages/bmp/WriteSerialFlash.java | 2 +- .../ac/manchester/spinnaker/messages/boot/BootDataBlock.java | 2 +- .../manchester/spinnaker/messages/boot/EndOfBootMessages.java | 2 +- .../spinnaker/messages/boot/StartOfBootMessages.java | 2 +- .../manchester/spinnaker/messages/eieio/EventStopRequest.java | 2 +- .../ac/manchester/spinnaker/messages/eieio/HostDataRead.java | 2 +- .../manchester/spinnaker/messages/eieio/HostDataReadAck.java | 2 +- .../spinnaker/messages/eieio/HostSendSequencedData.java | 2 +- .../manchester/spinnaker/messages/eieio/KeyDataElement.java | 4 ++-- .../spinnaker/messages/eieio/KeyPayloadDataElement.java | 4 ++-- .../manchester/spinnaker/messages/eieio/PaddingRequest.java | 2 +- .../spinnaker/messages/eieio/SpinnakerRequestBuffers.java | 2 +- .../spinnaker/messages/eieio/SpinnakerRequestReadData.java | 2 +- .../ac/manchester/spinnaker/messages/eieio/StartRequests.java | 2 +- .../ac/manchester/spinnaker/messages/eieio/StopRequests.java | 2 +- .../ac/manchester/spinnaker/messages/scp/ApplicationRun.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/CountState.java | 2 +- .../ac/manchester/spinnaker/messages/scp/EmptyResponse.java | 2 +- .../ac/manchester/spinnaker/messages/scp/FloodFillData.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/GetChipInfo.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/GetVersion.java | 4 ++-- .../uk/ac/manchester/spinnaker/messages/scp/IPTagClear.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/IPTagGet.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/IPTagSetTTO.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/ReadLink.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java | 2 +- .../ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/RouterClear.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/RouterInit.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/SendSignal.java | 2 +- .../java/uk/ac/manchester/spinnaker/messages/scp/SetLED.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/WriteLink.java | 2 +- .../uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java | 2 +- 61 files changed, 68 insertions(+), 64 deletions(-) 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 9d0497cf4b..200a0cad03 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/Jobs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Jobs.java index c72cd7d4a6..d8573e842a 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 0e502ba9c1..1f7d360e29 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 985fe0efcd..51dbde9407 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/RootInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/RootInfo.java index 4b4b8e2072..573eecc80b 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/messages/bmp/GetBMPVersion.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/GetBMPVersion.java index d3342c382c..7b34494a66 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 02f127bca2..053caaf180 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 Which board to get the FPGA reset status of. */ public GetFPGAResetStatus(BMPBoard 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 f8f08982f8..31ce0da74b 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 65b880fa5f..f708dc2941 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 @@ -33,7 +33,7 @@ * right element of {@code board_stat}. The underlying data is synched from the * ADC approximately every 80ms by {@code read_adc()} in {@code bmp_hw.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/ReadBMPMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java index 8f9b0bb440..046f852c6d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java @@ -32,7 +32,7 @@ *

* Calls {@code cmd_read()} in {@code bmp_cmd.c}. */ -public class ReadBMPMemory 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( 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 a502a624c7..7cd5b02377 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 14a20b60ae..9c37d4e128 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. 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 3118b876a1..f725358a0a 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 @@ -35,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 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 9aa0c0b777..38d283296f 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 @@ -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( 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 e99daaf5de..3decd44c11 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 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 a84b8eac5d..5a855fda68 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 @@ -33,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 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 c61654b221..3c5609ba4a 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/SetBoardLEDs.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.java index 1e39347869..bf4e358744 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SetBoardLEDs.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 SetBoardLEDs extends BMPRequest { +public final class SetBoardLEDs extends BMPRequest { /** * Make a request. * 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 6bd0408d9f..f08049c4b2 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); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.java index f7e07bb33f..997b268447 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteBMPMemory.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 WriteBMPMemory extends BMPRequest { +public final class WriteBMPMemory extends BMPRequest { /** * @param board * the board with the BMP to write the memory of 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 d1ea475d58..d3844713e3 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 d8f9403ef7..60450892f6 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 @@ -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. 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 44d004b1fb..0aabe84120 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; 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 d96bf7a892..da84efc0e7 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; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootDataBlock.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootDataBlock.java index 224d4c907f..2f4c490e70 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootDataBlock.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootDataBlock.java @@ -27,7 +27,7 @@ * * @author Donal Fellows */ -class BootDataBlock extends BootMessage { +final class BootDataBlock extends BootMessage { private static final int BOOT_DATA_OPERAND_1 = (BOOT_MESSAGE_DATA_WORDS - 1) << NBBY; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/EndOfBootMessages.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/EndOfBootMessages.java index 26727445f0..53ca85b8d6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/EndOfBootMessages.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/EndOfBootMessages.java @@ -22,7 +22,7 @@ * * @author Donal Fellows */ -class EndOfBootMessages extends BootMessage { +final class EndOfBootMessages extends BootMessage { EndOfBootMessages() { super(FLOOD_FILL_CONTROL, 1, 0, 0); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/StartOfBootMessages.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/StartOfBootMessages.java index 08fcbf13af..0783162968 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/StartOfBootMessages.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/StartOfBootMessages.java @@ -22,7 +22,7 @@ * * @author Donal Fellows */ -class StartOfBootMessages extends BootMessage { +final class StartOfBootMessages extends BootMessage { /** * @param numPackets * The number of payload packets to be sent. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EventStopRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EventStopRequest.java index e73cbf40bf..8bacd527bc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EventStopRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EventStopRequest.java @@ -21,7 +21,7 @@ * Packet used for the buffering input technique which causes the parser of the * input packet to terminate its execution. */ -public class EventStopRequest extends EIEIOCommandMessage { +public final class EventStopRequest extends EIEIOCommandMessage { /** Make a request to stop sending events. */ public EventStopRequest() { super(EVENT_STOP); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataRead.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataRead.java index 81e69fe9da..79a1565cbc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataRead.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataRead.java @@ -28,7 +28,7 @@ * * @see HostDataReadAck */ -public class HostDataRead extends EIEIOCommandMessage { +public final class HostDataRead extends EIEIOCommandMessage { private final Header header; private final Ack acks; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataReadAck.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataReadAck.java index 12505f6b8f..8ec9fb9382 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataReadAck.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostDataReadAck.java @@ -26,7 +26,7 @@ * * @see HostDataRead */ -public class HostDataReadAck extends EIEIOCommandMessage { +public final class HostDataReadAck extends EIEIOCommandMessage { /** The message sequence number that is being acknowledged. */ public final byte sequenceNumber; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostSendSequencedData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostSendSequencedData.java index 43508b7b70..f99b94ce34 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostSendSequencedData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/HostSendSequencedData.java @@ -26,7 +26,7 @@ * input mechanism to identify packet which needs to be stored in memory for * future use. */ -public class HostSendSequencedData extends EIEIOCommandMessage { +public final class HostSendSequencedData extends EIEIOCommandMessage { /** What region will be moved. */ public final int regionID; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java index 6f2db8cc54..00c3ad6ec8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyDataElement.java @@ -18,7 +18,7 @@ import java.nio.ByteBuffer; /** A data element that contains just a key. */ -public class KeyDataElement implements AbstractDataElement { +public final class KeyDataElement implements AbstractDataElement { private final int key; /** @@ -30,7 +30,7 @@ public KeyDataElement(int key) { } @Override - public final void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { + public void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { if (eieioType.payloadBytes != 0) { throw new IllegalArgumentException( "The type specifies a payload, but this element has no" diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java index c1b196307e..455449f45f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/KeyPayloadDataElement.java @@ -18,7 +18,7 @@ import java.nio.ByteBuffer; /** A data element that contains a key and a payload. */ -public class KeyPayloadDataElement implements AbstractDataElement { +public final class KeyPayloadDataElement implements AbstractDataElement { private final int key; private final int payload; @@ -47,7 +47,7 @@ public boolean isTimestamp() { } @Override - public final void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { + public void addToBuffer(ByteBuffer buffer, EIEIOType eieioType) { if (eieioType.payloadBytes == 0) { throw new IllegalArgumentException( "The type specifies no payload, but this element has a" diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/PaddingRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/PaddingRequest.java index 15ad7a3912..cc7d1a0751 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/PaddingRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/PaddingRequest.java @@ -20,7 +20,7 @@ /** * Packet used to pad space in the buffering area, if needed. */ -public class PaddingRequest extends EIEIOCommandMessage { +public final class PaddingRequest extends EIEIOCommandMessage { /** Make an instance. */ public PaddingRequest() { super(EVENT_PADDING); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestBuffers.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestBuffers.java index 75bfd9917a..e9d0b32687 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestBuffers.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestBuffers.java @@ -28,7 +28,7 @@ * the SpiNNaker system to the host computer to ask for more data to inject * during the simulation. */ -public class SpinnakerRequestBuffers extends EIEIOCommandMessage +public final class SpinnakerRequestBuffers extends EIEIOCommandMessage implements HasCoreLocation { /** What core are we talking about. */ public final HasCoreLocation core; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestReadData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestReadData.java index ea0d0aa2d8..27eb9e02fe 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestReadData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/SpinnakerRequestReadData.java @@ -28,7 +28,7 @@ * from the SpiNNaker system to the host computer to signal that some data is * available to be read. */ -public class SpinnakerRequestReadData extends EIEIOCommandMessage +public final class SpinnakerRequestReadData extends EIEIOCommandMessage implements HasCoreLocation { private final int numRequests; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StartRequests.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StartRequests.java index 39fced497e..426becfde6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StartRequests.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StartRequests.java @@ -22,7 +22,7 @@ * to the SpiNNaker system that, if needed, it is possible to send more * "SpinnakerRequestBuffers" packet. */ -public class StartRequests extends EIEIOCommandMessage { +public final class StartRequests extends EIEIOCommandMessage { /** Make an instance. */ public StartRequests() { super(START_SENDING_REQUESTS); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StopRequests.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StopRequests.java index 66a6aa9f31..f555dd1a5a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StopRequests.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/StopRequests.java @@ -22,7 +22,7 @@ * to the SpiNNaker system that to stop sending "SpinnakerRequestBuffers" * packet. */ -public class StopRequests extends EIEIOCommandMessage { +public final class StopRequests extends EIEIOCommandMessage { /** Make an instance. */ public StopRequests() { super(STOP_SENDING_REQUESTS); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java index b42bdda306..8a07fdbed3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ApplicationRun.java @@ -41,7 +41,7 @@ * Calls {@code proc_start_app()} in {@code scamp-app.c}. */ @UsedInJavadocOnly(SystemVariableDefinition.class) -public class ApplicationRun extends SCPRequest { +public final class ApplicationRun extends SCPRequest { private static final int WAIT_BIT = 18; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java index 10b5674b8b..1d6d6a8f27 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/CountState.java @@ -37,7 +37,7 @@ * {@code p2p_region()} in {@code scamp-cmd.c}. This is the main use of * point-to-point signals (and the only one exposed to users). */ -public class CountState extends SCPRequest { +public final class CountState extends SCPRequest { /* enum send_reg_ctrl */ private static final int APP_STAT = 1; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java index 13c9fa7849..9c23b720bc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java @@ -22,7 +22,7 @@ /** * An SCP response to a request which has an empty payload. */ -public class EmptyResponse extends CheckOKResponse { +public final class EmptyResponse extends CheckOKResponse { /** * Create an instance. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java index 90966c6b83..2a62ec9a57 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillData.java @@ -41,7 +41,7 @@ * @see FloodFillStart * @see FloodFillEnd */ -public class FloodFillData extends SCPRequest { +public final class FloodFillData extends SCPRequest { private static final int FFD_NNP_FORWARD_RETRY = (FORWARD_LINKS << BYTE3) | ((DELAY | DATA_RESEND) << BYTE2); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetChipInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetChipInfo.java index fce2c2f9b8..112064f4ad 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetChipInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetChipInfo.java @@ -29,7 +29,7 @@ *

* Calls {@code cmd_info()} in {@code scamp-cmd.c}. */ -public class GetChipInfo extends SCPRequest { +public final class GetChipInfo extends SCPRequest { private static final int FLAGS = 0x5F; private static final int SIZE_FLAG = 0x20; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetVersion.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetVersion.java index 5858257b86..7a7eaa76c1 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetVersion.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/GetVersion.java @@ -30,7 +30,7 @@ * Calls {@code cmd_ver()} in {@code scamp-cmd.c} or {@code sark_cmd_ver()} in * {@code sark_base.c}, depending on which core the message is sent to. */ -public class GetVersion extends SCPRequest { +public final class GetVersion extends SCPRequest { /** * @param core * The location of the core to read from. @@ -46,7 +46,7 @@ public Response getSCPResponse(ByteBuffer buffer) } /** An SCP response to a request for the version of software running. */ - // Used in tests + // Used in TestUDPConnection public static final class Response extends PayloadedResponse { Response(ByteBuffer buffer) throws UnexpectedResponseCodeException { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagClear.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagClear.java index fc1a019de6..fb972ab9f9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagClear.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagClear.java @@ -32,7 +32,7 @@ * Handled by {@code cmd_iptag()} in {@code scamp-cmd.c} (or {@code bmp_cmd.c}, * if sent to a BMP). */ -public class IPTagClear extends SCPRequest { +public final class IPTagClear extends SCPRequest { /** * @param chip * The chip to clear the tag on. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGet.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGet.java index 333e61ab71..0fd3f43d56 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGet.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGet.java @@ -42,7 +42,7 @@ * Handled by {@code cmd_iptag()} in {@code scamp-cmd.c} (or {@code bmp_cmd.c}, * if sent to a BMP). */ -public class IPTagGet extends SCPRequest +public final class IPTagGet extends SCPRequest implements ConnectionAwareMessage { private final int tag; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java index 9901c1cfda..db040c0dae 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java @@ -36,7 +36,7 @@ * * @see IPTagGet */ -public class IPTagGetInfo extends SCPRequest { +public final class IPTagGetInfo extends SCPRequest { private static final int IPTAG_MAX = 255; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java index bb28893b8f..6ff711858d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSet.java @@ -51,7 +51,7 @@ * * @see ReverseIPTagSet */ -public class IPTagSet extends SCPRequest { +public final class IPTagSet extends SCPRequest { private static final Logger log = getLogger(IPTagSet.class); private static final int INADDRSZ = 4; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSetTTO.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSetTTO.java index 14c2955982..cabaa94928 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSetTTO.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagSetTTO.java @@ -35,7 +35,7 @@ * Handled by {@code cmd_iptag()} in {@code scamp-cmd.c} (or {@code bmp_cmd.c}, * if sent to a BMP). */ -public class IPTagSetTTO extends SCPRequest { +public final class IPTagSetTTO extends SCPRequest { /** * @param chip * The chip to set the tag timout on. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java index e61f6cff86..76b8c3a32b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java @@ -34,7 +34,7 @@ *

* Calls {@code cmd_link_read()} in {@code scamp-cmd.c}. */ -public class ReadLink extends SCPRequest { +public final class ReadLink extends SCPRequest { private static int validate(int size) { if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) { throw new IllegalArgumentException( diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java index 2b4842b2a9..03351b1dbe 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java @@ -33,7 +33,7 @@ *

* Calls {@code sark_cmd_read()} in {@code sark_base.c}. */ -public class ReadMemory extends SCPRequest { +public final class ReadMemory extends SCPRequest { private static int validate(int size) { if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) { throw new IllegalArgumentException( diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java index 909c5d2742..e47139804f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReverseIPTagSet.java @@ -48,7 +48,7 @@ * * @see IPTagSet */ -public class ReverseIPTagSet extends SCPRequest { +public final class ReverseIPTagSet extends SCPRequest { /** * @param chip * The chip to set the tag on. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java index 359d1cefc4..3f07069def 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterAlloc.java @@ -35,7 +35,7 @@ * Calls {@code rtr_alloc_id()} in {@code sark_alloc.c} via {@code cmd_alloc()} * in {@code scamp-cmd.c}. */ -public class RouterAlloc extends SCPRequest { +public final class RouterAlloc extends SCPRequest { private final int numEntries; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterClear.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterClear.java index 4dad80f753..db5e94e3d8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterClear.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterClear.java @@ -29,7 +29,7 @@ * Calls {@code rtr_mc_init()} in {@code sark_hw.c}, via {@code rtr_cmd()} in * {@code scamp-cmd.c}. */ -public class RouterClear extends SCPRequest { +public final class RouterClear extends SCPRequest { /** * @param chip * The coordinates of the chip to clear the router of diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java index 705d8fe896..c17b9164b2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterInit.java @@ -34,7 +34,7 @@ * Ultimately handled by {@code rtr_mc_load()} in {@code sark_hw.c} (via * {@code cmd_rtr()} in {@code scamp-cmd.c}). */ -public class RouterInit extends SCPRequest { +public final class RouterInit extends SCPRequest { /** One reserved for SCAMP. */ private static final int MAX_ENTRIES = 1023; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java index b9a095d217..fe611790c6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMAlloc.java @@ -37,7 +37,7 @@ * Calls {@code cmd_alloc()} (and hence {@code sark_xalloc()}) in * {@code scamp-cmd.c}. */ -public class SDRAMAlloc extends SCPRequest { +public final class SDRAMAlloc extends SCPRequest { private static final int MAX_SDRAM_TAG = 255; private static final int FLAG_TAG_RETRY = 4; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java index 4b846a0054..358b8cae46 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SDRAMDeAlloc.java @@ -36,7 +36,7 @@ * Calls {@code cmd_alloc()} (and hence {@code sark_xfree()} or * {@code sark_xfree_id()}) in {@code scamp-cmd.c}. */ -public class SDRAMDeAlloc extends SCPRequest { +public final class SDRAMDeAlloc extends SCPRequest { private final boolean readNumFreedBlocks; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java index 1a59e9b5e2..c7dda88e8c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SendSignal.java @@ -41,7 +41,7 @@ * * @see CountState */ -public class SendSignal extends SCPRequest { +public final class SendSignal extends SCPRequest { /** * @param appID * The ID of the application to signal (only for multicast diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetLED.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetLED.java index caacad5ac8..47f2a450f0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetLED.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/SetLED.java @@ -29,7 +29,7 @@ *

* Handled by {@code sark_led_set()} in {@code sark_hw.c}. */ -public class SetLED extends SCPRequest { +public final class SetLED extends SCPRequest { /** * @param core * The SpiNNaker core that will set the BMPSetLED diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java index 3b148d62d4..58d038675d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteLink.java @@ -30,7 +30,7 @@ *

* Calls {@code cmd_link_write()} in {@code scamp-cmd.c}. */ -public class WriteLink extends SCPRequest { +public final class WriteLink extends SCPRequest { /** * @param core * the core to write via diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java index eafcadc7c1..6930c1a64b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/WriteMemory.java @@ -30,7 +30,7 @@ *

* Calls {@code sark_cmd_write()} in {@code sark_base.c}. */ -public class WriteMemory extends SCPRequest { +public final class WriteMemory extends SCPRequest { /** * @param core * the core to write via From 6bb2b8a09f260e28c5753d1b0a6c5bb216801326 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 13 Feb 2023 11:58:14 +0000 Subject: [PATCH 053/194] More final classes, use ceildiv more I now know that we don't currently use WriteMemoryFloodProcess in reality; the block count was off by a factor of 4 --- .../ac/manchester/spinnaker/messages/boot/BootMessages.java | 5 ++--- .../uk/ac/manchester/spinnaker/messages/model/CPUInfo.java | 2 +- .../uk/ac/manchester/spinnaker/messages/model/ChipInfo.java | 2 +- .../spinnaker/messages/model/DiagnosticFilter.java | 2 +- .../spinnaker/messages/model/ExecutableTargets.java | 2 +- .../uk/ac/manchester/spinnaker/messages/model/IOBuffer.java | 2 +- .../uk/ac/manchester/spinnaker/messages/model/P2PTable.java | 5 +++-- .../spinnaker/messages/model/RouterDiagnostics.java | 2 +- .../spinnaker/transceiver/WriteMemoryFloodProcess.java | 6 ++---- .../uk/ac/manchester/spinnaker/utils/CollectionUtils.java | 3 ++- 10 files changed, 15 insertions(+), 16 deletions(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java index 6830b07253..f7129286f6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java @@ -16,7 +16,6 @@ package uk.ac.manchester.spinnaker.messages.boot; import static java.lang.Integer.reverseBytes; -import static java.lang.Math.ceil; import static java.lang.Math.min; import static java.lang.String.format; import static java.lang.System.currentTimeMillis; @@ -30,6 +29,7 @@ import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.boot_signature; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.is_root_chip; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.unix_timestamp; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC; import java.io.DataInputStream; @@ -86,8 +86,7 @@ private BootMessages(SystemVariableBootValues bootVariables, } bootData = readBootImage(getClass().getResource(BOOT_IMAGE)); injectBootVariableBlock(bootVariables); - numDataPackets = - (int) ceil(bootData.limit() / (float) BOOT_MESSAGE_DATA_BYTES); + numDataPackets = ceildiv(bootData.limit(), BOOT_IMAGE_MAX_BYTES); } private void injectBootVariableBlock( diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/CPUInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/CPUInfo.java index 97115af140..56ff976064 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/CPUInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/CPUInfo.java @@ -36,7 +36,7 @@ /** Represents information about the state of a CPU. */ @SARKStruct("vcpu") -public class CPUInfo implements HasCoreLocation { +public final class CPUInfo implements HasCoreLocation { private final CoreLocation core; @SARKField("r") diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java index 6607bd02a8..5c71ec8bfb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java @@ -117,7 +117,7 @@ /** * Represents the system variables for a chip, received from the chip SDRAM. */ -public class ChipInfo implements HasChipLocation { +public final class ChipInfo implements HasChipLocation { private static final byte[] NO_IP = { 0, 0, 0, 0 }; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/DiagnosticFilter.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/DiagnosticFilter.java index 6ebe20d295..c6384fe87d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/DiagnosticFilter.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/DiagnosticFilter.java @@ -30,7 +30,7 @@ * of the destinations, sources, payload statuses, default routing statuses, * emergency routing statuses, and packet types. */ -public class DiagnosticFilter { +public final class DiagnosticFilter { private static final int PACKET_TYPE_OFFSET = 0; private static final int EMERGENCY_ROUTE_OFFSET = 4; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java index 2bc7c5fd8c..3ac9e1c9fd 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ExecutableTargets.java @@ -29,7 +29,7 @@ import uk.ac.manchester.spinnaker.machine.CoreSubsets; /** Encapsulate the binaries and cores on which to execute them. */ -public class ExecutableTargets { +public final class ExecutableTargets { private final Map<@NotBlank String, @Valid CoreSubsets> targets; @PositiveOrZero diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java index de8ac472d1..b1ce08990d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java @@ -32,7 +32,7 @@ * * @author Donal Fellows */ -public class IOBuffer implements HasCoreLocation { +public final class IOBuffer implements HasCoreLocation { private final HasCoreLocation core; private final byte[] iobuf; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java index b8708bde2d..6c43ba5626 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/P2PTable.java @@ -20,6 +20,7 @@ import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.model.P2PTableRoute.NONE; import static uk.ac.manchester.spinnaker.utils.CollectionUtils.copy; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.nio.ByteBuffer; import java.util.Collection; @@ -34,7 +35,7 @@ import uk.ac.manchester.spinnaker.machine.ValidMachineWidth; /** Represents a P2P routing table read from the machine. */ -public class P2PTable { +public final class P2PTable { private final Map routes; /** The width of the machine that this table represents. */ @@ -101,7 +102,7 @@ private void extractRoutes(int chipX, int chipYBase, int word) { * @return The number of bytes for the column */ public static int getNumColumnBytes(int height) { - return ((height + NBBY - 1) / NBBY) * WORD_SIZE; + return ceildiv(height, NBBY) * WORD_SIZE; } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterDiagnostics.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterDiagnostics.java index d883f31775..7dc3226473 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterDiagnostics.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/RouterDiagnostics.java @@ -37,7 +37,7 @@ /** * Represents a set of diagnostic information available from a chip router. */ -public class RouterDiagnostics { +public final class RouterDiagnostics { /** The "mon" part of the control register. */ public final int mon; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java index 21a24fb54b..1c886aa169 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java @@ -15,12 +15,12 @@ */ package uk.ac.manchester.spinnaker.transceiver; -import static java.lang.Math.ceil; import static java.nio.ByteBuffer.allocate; import static org.apache.commons.io.IOUtils.buffer; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.read; import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.io.File; import java.io.FileInputStream; @@ -51,10 +51,8 @@ class WriteMemoryFloodProcess extends TxrxProcess { super(connectionSelector, retryTracker); } - private static final float BPW = 4.0F; - private static int numBlocks(int numBytes) { - return (int) ceil(ceil(numBytes / BPW) / UDP_MESSAGE_MAX_SIZE); + return ceildiv(numBytes, UDP_MESSAGE_MAX_SIZE); } /** diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java index 94769007db..c917fb2b1c 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java @@ -26,6 +26,7 @@ import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toUnmodifiableList; import static java.util.stream.Collectors.toUnmodifiableMap; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.util.ArrayList; import java.util.Collection; @@ -146,7 +147,7 @@ public static Function curry(BiFunction fn, */ public static Collection> batch(int batchSize, List input) { - return IntStream.range(0, (input.size() + batchSize - 1) / batchSize) + return IntStream.range(0, ceildiv(input.size(), batchSize)) .map(i -> i * batchSize) .mapToObj(idx -> unmodifiableCollection( input.subList(idx, min(input.size(), idx + batchSize)))) From 0f12303f38dc529ed293a1c978cf02dd9a17a9f8 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 13 Feb 2023 14:58:21 +0000 Subject: [PATCH 054/194] Wrong constant --- .../uk/ac/manchester/spinnaker/messages/boot/BootMessages.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java index f7129286f6..45566140e2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java @@ -86,7 +86,7 @@ private BootMessages(SystemVariableBootValues bootVariables, } bootData = readBootImage(getClass().getResource(BOOT_IMAGE)); injectBootVariableBlock(bootVariables); - numDataPackets = ceildiv(bootData.limit(), BOOT_IMAGE_MAX_BYTES); + numDataPackets = ceildiv(bootData.limit(), BOOT_MESSAGE_DATA_BYTES); } private void injectBootVariableBlock( From 60e56e015d0f98862783d510c9585ac51309bf90 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 14 Feb 2023 09:01:50 +0000 Subject: [PATCH 055/194] More strongly label what is text for git --- .gitattributes | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 1564a7b813..68b9f5322c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +* text *.sql linguist-language=SQL linguist-detectable *.cff linguist-language=YAML *.json linguist-detectable @@ -5,8 +6,12 @@ *.yml linguist-detectable *.cfg linguist-language=INI linguist-detectable *.properties linguist-language=Java-Properties linguist-detectable -*.bin -linguist-generated -*.boot -linguist-generated -*.aplx -linguist-generated +*.bin binary -linguist-generated +*.boot binary -linguist-generated +*.aplx binary -linguist-generated *.fig linguist-documentation SpiNNaker-py2json/src/main/python/enum.py linguist-vendored +*.bit binary -linguist-generated +*.png binary +*.jpg binary +*/package-list linguist-generated From e3e515cc849e2c5a74fc3288d6226263c5c10da0 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 14 Feb 2023 12:46:07 +0000 Subject: [PATCH 056/194] eolfix --- .mvn/jvm.config | 20 +- .../spinnaker/alloc/ForTestingOnly.java | 152 +- .../manchester/spinnaker/alloc/IOUtils.java | 150 +- .../alloc/admin/AdminControllerSupport.java | 890 +++++------ .../alloc/admin/ReportMailSender.java | 184 +-- .../alloc/bmp/BlacklistOperation.java | 62 +- .../spinnaker/alloc/bmp/BlacklistStore.java | 402 ++--- .../alloc/bmp/PhysicalSerialMapping.java | 234 +-- .../spinnaker/alloc/compat/SaneParameter.java | 152 +- .../spinnaker/alloc/compat/TaskException.java | 64 +- .../spinnaker/alloc/db/DatabaseAPI.java | 1298 ++++++++--------- .../spinnaker/alloc/model/Utils.java | 110 +- .../alloc/security/OpenIDUserAware.java | 200 +-- ...itional-spring-configuration-metadata.json | 2 +- .../spinnaker/alloc/SupportQueries.java | 370 ++--- .../spinnaker/alloc/TestSupport.java | 1060 +++++++------- .../spinnaker/alloc/bmp/MockTransceiver.java | 582 ++++---- .../spinnaker/alloc/db/MemDBTestBase.java | 130 +- .../test/resources/three-board-example.json | 2 +- .../spinnaker/alloc/client/ClientUtils.java | 172 +-- .../alloc/client/ProxiedBootConnection.java | 208 +-- .../ProxiedEIEIOListenerConnection.java | 194 +-- .../alloc/client/ProxiedSCPConnection.java | 230 +-- .../alloc/client/ProxiedTransceiver.java | 182 +-- .../spinnaker/alloc/client/ProxyProtocol.java | 106 +- .../alloc/client/ProxyProtocolClient.java | 232 +-- .../spinnaker/alloc/client/Session.java | 400 ++--- .../manchester/spinnaker/messages/Utils.java | 90 +- .../spinnaker/messages/bmp/SerialVector.java | 238 +-- .../spinnaker/messages/model/Addresses.java | 78 +- .../spinnaker/messages/model/Blacklist.java | 1108 +++++++------- .../messages/model/TagDescription.java | 358 ++--- .../spinnaker/messages/model/TagInfo.java | 98 +- .../model/UnroutableMessageException.java | 90 +- .../messages/scp/ConnectionAwareMessage.java | 82 +- .../spinnaker/messages/scp/EmptyResponse.java | 84 +- .../spinnaker/messages/scp/FECRequest.java | 170 +-- .../messages/scp/FloodFillConstants.java | 82 +- .../messages/scp/PayloadedResponse.java | 122 +- .../messages/scp/ReinjectorRequest.java | 184 +-- .../messages/scp/RouterTableRequest.java | 150 +- .../spinnaker/spalloc/messages/BoardLink.java | 196 +-- .../transceiver/CommonMemoryLocations.java | 218 +-- .../spinnaker/messages/model/TestVersion.java | 116 +- .../messages/TestBoardCoordinates.java | 94 +- .../TestBoardPhysicalCoordinates.java | 94 +- .../spalloc/messages/TestJobDescription.java | 172 +-- .../spalloc/messages/TestJobMachineInfo.java | 132 +- .../spalloc/messages/TestMachine.java | 180 +-- .../spinnaker/spalloc/messages/TestState.java | 126 +- .../spalloc/messages/TestWhereIs.java | 220 +-- .../src/test/resources/spinn2.json | 2 +- .../src/test/resources/spinn4.json | 2 +- .../spinnaker/alloc/bmp/example.blacklist | 36 +- .../dse/ExecuteDataSpecification.java | 254 ++-- .../src/test/resources/gather.json | 2 +- .../src/test/resources/machine.json | 32 +- .../src/test/resources/simple.json | 2 +- .../spinnaker/front_end/iobuf/empty.dict | 32 +- .../spinnaker/machine/MemoryLocation.java | 314 ++-- .../spinnaker/machine/ValidMachineHeight.java | 138 +- .../spinnaker/machine/ValidMachineWidth.java | 138 +- .../manchester/spinnaker/machine/ValidP.java | 136 +- .../manchester/spinnaker/machine/ValidX.java | 136 +- .../manchester/spinnaker/machine/ValidY.java | 136 +- .../spinnaker/machine/board/BMPCoords.java | 400 ++--- .../machine/board/DeserializerHelper.java | 406 +++--- .../spinnaker/machine/board/Limits.java | 94 +- .../machine/board/PhysicalCoords.java | 416 +++--- .../spinnaker/machine/board/TriadCoords.java | 460 +++--- .../machine/board/ValidBoardNumber.java | 138 +- .../machine/board/ValidCabinetNumber.java | 138 +- .../machine/board/ValidFrameNumber.java | 138 +- .../machine/board/ValidTriadDepth.java | 140 +- .../machine/board/ValidTriadHeight.java | 136 +- .../machine/board/ValidTriadWidth.java | 136 +- .../spinnaker/machine/board/ValidTriadX.java | 136 +- .../spinnaker/machine/board/ValidTriadY.java | 136 +- .../spinnaker/machine/board/ValidTriadZ.java | 136 +- .../spinnaker/machine/board/package-info.java | 42 +- .../spinnaker/machine/tags/TagID.java | 206 +-- .../src/test/resources/h40w16.json | 2 +- .../src/test/resources/spinn2.json | 2 +- .../src/test/resources/spinn4.json | 2 +- .../src/test/resources/spinn4_fiddle.json | 2 +- .../src/test/resources/test24_12.json | 2 +- SpiNNaker-pacman/src/test/java/.gitignore | 1 + .../spinnaker/py2json/Configuration.java | 162 +- .../ac/manchester/spinnaker/py2json/Link.java | 86 +- .../manchester/spinnaker/py2json/Machine.java | 352 ++--- .../py2json/WithCurrentDirectory.java | 110 +- .../spinnaker/py2json/three_board.py | 82 +- .../spinnaker/storage/sqlite/Ordinals.java | 74 +- .../storage/sqlite/ResourceLoader.java | 122 +- .../spinnaker/utils/ByteBufferUtils.java | 252 ++-- .../spinnaker/utils/CollectionUtils.java | 620 ++++---- .../ac/manchester/spinnaker/utils/Daemon.java | 166 +-- .../spinnaker/utils/UsedInJavadocOnly.java | 88 +- .../spinnaker/utils/validation/TCPPort.java | 252 ++-- .../spinnaker/utils/validation/UDPPort.java | 250 ++-- .../utils/validation/package-info.java | 38 +- .../spinnaker/utils/TestOneShotEvent.java | 258 ++-- .../com.fasterxml.jackson.core/package-list | 28 +- .../package-list | 46 +- .../javadoc/javax.validation/package-list | 18 +- src/support/javadoc/javax.ws.rs/package-list | 12 +- .../javadoc/org.keycloak.client/package-list | 2 +- .../javadoc/org.keycloak.core/package-list | 6 +- 108 files changed, 9962 insertions(+), 9961 deletions(-) diff --git a/.mvn/jvm.config b/.mvn/jvm.config index 3ed5dea48c..32599cefea 100644 --- a/.mvn/jvm.config +++ b/.mvn/jvm.config @@ -1,10 +1,10 @@ ---add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED ---add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ---add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java index cdd19fecd9..302eed6fd3 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import java.lang.StackWalker.StackFrame; -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.Arrays; - -/** - * Marks a type or method that only exists for testing purposes. Do not use for - * any other reason! Methods tagged with this should also be tagged - * {@link Deprecated @Deprecated}; classes/interfaces tagged with this need not. - * - * @author Donal Fellows - */ -@Documented -@Retention(CLASS) -@Target({ TYPE, METHOD }) -public @interface ForTestingOnly { - /** Utilities for checking the promises relating to the annotation. */ - abstract class Utils { - /** - * The name of the class used to annotate tests that can access - * bean test APIs. - */ - private static final String SPRING_BOOT_TEST = - "org.springframework.boot.test.context.SpringBootTest"; - - private Utils() { - } - - /** - * A simple test for whether there are classes annotated with - * {@code @SpringBootTest} on the stack at the point it is called. - * Moderately expensive, but it only guards stuff that should be used on - * test paths, so that isn't important. - * - * @throws Error - * if not called from the right place; it's a serious - * security failure and wrong programming. - */ - // No link to doc; built in code that doesn't see test classes - public static void checkForTestClassOnStack() { - if (!StackWalker.getInstance(RETAIN_CLASS_REFERENCE) - .walk(s -> s.map(StackFrame::getDeclaringClass) // - .map(Class::getAnnotations) // - .flatMap(Arrays::stream) // - .map(Annotation::annotationType) // - .map(Class::getName) // - .anyMatch(SPRING_BOOT_TEST::equals))) { - throw new Error("test-only code called from non-test context"); - } - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.StackWalker.StackFrame; +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.Arrays; + +/** + * Marks a type or method that only exists for testing purposes. Do not use for + * any other reason! Methods tagged with this should also be tagged + * {@link Deprecated @Deprecated}; classes/interfaces tagged with this need not. + * + * @author Donal Fellows + */ +@Documented +@Retention(CLASS) +@Target({ TYPE, METHOD }) +public @interface ForTestingOnly { + /** Utilities for checking the promises relating to the annotation. */ + abstract class Utils { + /** + * The name of the class used to annotate tests that can access + * bean test APIs. + */ + private static final String SPRING_BOOT_TEST = + "org.springframework.boot.test.context.SpringBootTest"; + + private Utils() { + } + + /** + * A simple test for whether there are classes annotated with + * {@code @SpringBootTest} on the stack at the point it is called. + * Moderately expensive, but it only guards stuff that should be used on + * test paths, so that isn't important. + * + * @throws Error + * if not called from the right place; it's a serious + * security failure and wrong programming. + */ + // No link to doc; built in code that doesn't see test classes + public static void checkForTestClassOnStack() { + if (!StackWalker.getInstance(RETAIN_CLASS_REFERENCE) + .walk(s -> s.map(StackFrame::getDeclaringClass) // + .map(Class::getAnnotations) // + .flatMap(Arrays::stream) // + .map(Annotation::annotationType) // + .map(Class::getName) // + .anyMatch(SPRING_BOOT_TEST::equals))) { + throw new Error("test-only code called from non-test context"); + } + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java index 94a0c0df2c..411b63ee57 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * Utility wrappers for I/O. - * - * @author Donal Fellows - */ -public abstract class IOUtils { - private IOUtils() { - } - - /** - * Convert a serializable object into its serialized form. - * - * @param obj - * The object to serialize. - * @return The serialized form. - * @throws IOException - * If the object isn't serializable. - */ - public static byte[] serialize(Object obj) throws IOException { - var baos = new ByteArrayOutputStream(); - try (var oos = new ObjectOutputStream(baos)) { - oos.writeObject(obj); - } - return baos.toByteArray(); - } - - /** - * Convert a serialized object into its normal form. Only call on - * data that is trusted! - * - * @param - * The type of the response. - * @param bytes - * The serialized data. - * @param cls - * The class that the object is expected to conform to. - * @return The deserialized object. - * @throws IOException - * If the object isn't deserializable. - * @throws ClassNotFoundException - * If the data doesn't represent a known class. - * @throws ClassCastException - * If the data is not an object of the expected class. - */ - public static T deserialize(byte[] bytes, Class cls) - throws ClassNotFoundException, IOException { - var bais = new ByteArrayInputStream(bytes); - try (var ois = new ObjectInputStream(bais)) { - return cls.cast(ois.readObject()); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Utility wrappers for I/O. + * + * @author Donal Fellows + */ +public abstract class IOUtils { + private IOUtils() { + } + + /** + * Convert a serializable object into its serialized form. + * + * @param obj + * The object to serialize. + * @return The serialized form. + * @throws IOException + * If the object isn't serializable. + */ + public static byte[] serialize(Object obj) throws IOException { + var baos = new ByteArrayOutputStream(); + try (var oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } + return baos.toByteArray(); + } + + /** + * Convert a serialized object into its normal form. Only call on + * data that is trusted! + * + * @param + * The type of the response. + * @param bytes + * The serialized data. + * @param cls + * The class that the object is expected to conform to. + * @return The deserialized object. + * @throws IOException + * If the object isn't deserializable. + * @throws ClassNotFoundException + * If the data doesn't represent a known class. + * @throws ClassCastException + * If the data is not an object of the expected class. + */ + public static T deserialize(byte[] bytes, Class cls) + throws ClassNotFoundException, IOException { + var bais = new ByteArrayInputStream(bytes); + try (var ois = new ObjectInputStream(bais)) { + return cls.cast(ois.readObject()); + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java index ccd1508016..fa02497616 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java @@ -1,445 +1,445 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.admin; - -import static java.util.Collections.unmodifiableMap; - -import java.net.URI; -import java.util.List; -import java.util.Map; - -import org.springframework.ui.ModelMap; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; - -import uk.ac.manchester.spinnaker.alloc.admin.AdminController.BlacklistData; -import uk.ac.manchester.spinnaker.alloc.admin.MachineDefinitionLoader.Machine; -import uk.ac.manchester.spinnaker.alloc.model.BoardIssueReport; -import uk.ac.manchester.spinnaker.alloc.model.BoardRecord; -import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; -import uk.ac.manchester.spinnaker.alloc.model.MachineTagging; -import uk.ac.manchester.spinnaker.alloc.model.UserRecord; -import uk.ac.manchester.spinnaker.alloc.model.GroupRecord.GroupType; -import uk.ac.manchester.spinnaker.alloc.security.TrustLevel; -import uk.ac.manchester.spinnaker.alloc.web.ControllerUtils.ViewFactory; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * Support code for {@link AdminController}. - */ -@UsedInJavadocOnly({ GroupType.class, BoardIssueReport.class }) -interface AdminControllerSupport { - // These are paths below src/main/webapp/WEB-INF/views - /** View: {@code admin/index.jsp}. */ - ViewFactory MAIN_VIEW = new ViewFactory("admin/index"); - - /** View: {@code admin/listusers.jsp}. */ - ViewFactory USER_LIST_VIEW = new ViewFactory("admin/listusers"); - - /** View: {@code admin/userdetails.jsp}. */ - ViewFactory USER_DETAILS_VIEW = new ViewFactory("admin/userdetails"); - - /** View: {@code admin/createuser.jsp}. */ - ViewFactory CREATE_USER_VIEW = new ViewFactory("admin/createuser"); - - /** View: {@code admin/listgroups.jsp}. */ - ViewFactory GROUP_LIST_VIEW = new ViewFactory("admin/listgroups"); - - /** View: {@code admin/groupdetails.jsp}. */ - ViewFactory GROUP_DETAILS_VIEW = new ViewFactory("admin/groupdetails"); - - /** View: {@code admin/creategroup.jsp}. */ - ViewFactory CREATE_GROUP_VIEW = new ViewFactory("admin/creategroup"); - - /** View: {@code admin/board.jsp}. */ - ViewFactory BOARD_VIEW = new ViewFactory("admin/board"); - - /** View: {@code admin/machine.jsp}. */ - ViewFactory MACHINE_VIEW = new ViewFactory("admin/machine"); - - /** User list in {@link #USER_LIST_VIEW}. All users. */ - String USER_LIST_OBJ = "userlist"; - - /** User list in {@link #USER_LIST_VIEW}. Local users only. */ - String LOCAL_USER_LIST_OBJ = "localusers"; - - /** User list in {@link #USER_LIST_VIEW}. OpenID users only. */ - String OPENID_USER_LIST_OBJ = "openidusers"; - - /** User details in {@link #USER_DETAILS_VIEW}. */ - String USER_OBJ = "user"; - - /** - * Group list (type: {@link GroupType#INTERNAL}) in - * {@link #GROUP_LIST_VIEW}. - */ - String LOCAL_GROUP_LIST_OBJ = "localgroups"; - - /** - * Group list (type: {@link GroupType#ORGANISATION}) in - * {@link #GROUP_LIST_VIEW}. - */ - String ORG_GROUP_LIST_OBJ = "orggroups"; - - /** - * Group list (type: {@link GroupType#COLLABRATORY}) in - * {@link #GROUP_LIST_VIEW}. - */ - String COLLAB_GROUP_LIST_OBJ = "collabgroups"; - - /** - * Group details in {@link #GROUP_DETAILS_VIEW}. Group creation info in - * {@link #CREATE_GROUP_VIEW}. - */ - String GROUP_OBJ = "group"; - - /** State in {@link #BOARD_VIEW}. {@link BoardRecord}. */ - String BOARD_OBJ = "board"; - - /** - * Blacklist data in {@link #BOARD_VIEW}. {@link BlacklistData}. - */ - String BLACKLIST_DATA_OBJ = "bldata"; - - /** - * Mapping from machine names to whether they're in service, in - * {@link #MACHINE_VIEW}. - * {@link Map}{@code <}{@link String}{@code ,}{@link Boolean}{@code >} - */ - String MACHINE_LIST_OBJ = "machineNames"; - - /** - * Machines that have been defined, in {@link #MACHINE_VIEW}. - * - * @see Machine - */ - String DEFINED_MACHINES_OBJ = "definedMachines"; - - /** - * Result of {@link MachineStateControl#getMachineTagging()}, in - * {@link #MACHINE_VIEW}. - * - * @see MachineTagging - */ - String MACHINE_TAGGING_OBJ = "machineTagging"; - - /** - * Number of {@code default} tags in {@link #MACHINE_TAGGING_OBJ}, in - * {@link #MACHINE_VIEW}. - */ - String DEFAULT_TAGGING_COUNT = "defaultCount"; - - /** - * Result of {@link MachineStateControl#getMachineReports()}, in - * {@link #MACHINE_VIEW}. - * - * @see BoardIssueReport - */ - String MACHINE_REPORTS_OBJ = "machineReports"; - - /** The base URI for the current request. In all views. */ - String BASE_URI = "baseuri"; - - /** The members of {@link TrustLevel}. In all views. */ - String TRUST_LEVELS = "trustLevels"; - - /** - * How to call {@link AdminController#listUsers() listUsers()}. In all - * views. - */ - String USERS_URI = "usersUri"; - - /** - * How to call {@link AdminController#getUserCreationForm() - * getUserCreationForm()}. In all views. - */ - String CREATE_USER_URI = "createUserUri"; - - /** - * How to call {@link AdminController#listGroups() listGroups()}. In all - * views. - */ - String GROUPS_URI = "groupsUri"; - - /** - * How to call {@link AdminController#getGroupCreationForm() - * getGroupCreationForm()}. In all views. - */ - String CREATE_GROUP_URI = "createGroupUri"; - - /** How to call {@link AdminController#boards() boards()}. In all views. */ - String BOARDS_URI = "boardsUri"; - - /** - * How to call {@link AdminController#blacklistSave(BlacklistData,ModelMap) - * blacklistSave()}, - * {@link AdminController#blacklistPush(BlacklistData, ModelMap) - * blacklistPush()}, and - * {@link AdminController#blacklistFetch(BlacklistData,ModelMap) - * blacklistFetch()}. In {@link #BOARD_VIEW}. - */ - String BLACKLIST_URI = "blacklistControlUri"; - - /** - * How to call {@link AdminController#machineManagement() - * machineManagement()}. In all views. - */ - String MACHINE_URI = "machineUri"; - - // Type-safe manipulators for models - // These are static so they *can't* access state they shouldn't - - /** - * Add local user list to model. - * - * @param mav - * The model - * @param userList - * The user list to add. - */ - static void addLocalUserList(ModelAndView mav, Map userList) { - mav.addObject(LOCAL_USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add openid-based (remote) user list to model. - * - * @param mav - * The model - * @param userList - * The user list to add. - */ - static void addRemoteUserList(ModelAndView mav, Map userList) { - mav.addObject(OPENID_USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add general user list to model. - * - * @param mav - * The model - * @param userList - * The group list to add. - */ - static void addUserList(ModelAndView mav, Map userList) { - mav.addObject(USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add user record to model. - * - * @param mav - * The model - * @param user - * The user record to add. - */ - static void addUser(ModelAndView mav, UserRecord user) { - mav.addObject(USER_OBJ, user.sanitise()); - } - - /** - * Add user record to model. - * - * @param attrs - * The model - * @param user - * The user record to add. - */ - static void addUser(RedirectAttributes attrs, UserRecord user) { - attrs.addFlashAttribute(USER_OBJ, user); - } - - /** - * Add local group list to model. - * - * @param mav - * The model - * @param groupList - * The group list to add. - */ - static void addLocalGroupList(ModelAndView mav, - Map groupList) { - mav.addObject(LOCAL_GROUP_LIST_OBJ, unmodifiableMap(groupList)); - } - - /** - * Add organisation list to model. - * - * @param mav - * The model - * @param orgList - * The group list to add. - */ - static void addOrganisationList(ModelAndView mav, - Map orgList) { - mav.addObject(ORG_GROUP_LIST_OBJ, unmodifiableMap(orgList)); - } - - /** - * Add collabratory list to model. - * - * @param mav - * The model - * @param collabList - * The group list to add. - */ - static void addCollabratoryList(ModelAndView mav, - Map collabList) { - mav.addObject(COLLAB_GROUP_LIST_OBJ, unmodifiableMap(collabList)); - } - - /** - * Add group record to model. - * - * @param mav - * The model - * @param group - * The group record to add. - */ - static void addGroup(ModelAndView mav, GroupRecord group) { - mav.addObject(GROUP_OBJ, group); - } - - /** - * Add board record to model. - * - * @param mav - * The model - * @param board - * The board record to add. - */ - static void addBoard(ModelAndView mav, BoardRecord board) { - mav.addObject(BOARD_OBJ, board); - } - - /** - * Add board record to model. - * - * @param model - * The model - * @param board - * The board record to add. - */ - static void addBoard(ModelMap model, BoardRecord board) { - model.addAttribute(BOARD_OBJ, board); - } - - /** - * Add blacklist record to model. - * - * @param model - * The model - * @param bldata - * The blacklist record to add. - */ - static void addBlacklist(ModelMap model, BlacklistData bldata) { - model.addAttribute(BLACKLIST_DATA_OBJ, bldata); - } - - /** - * Add machine list to model. - * - * @param mav - * The model - * @param machineList - * The machine list to add. - */ - static void addMachineList(ModelAndView mav, - Map machineList) { - mav.addObject(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); - } - - /** - * Add machine list to model. - * - * @param model - * The model - * @param machineList - * The machine list to add. - */ - static void addMachineList(ModelMap model, - Map machineList) { - model.addAttribute(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); - } - - /** - * Add machine tagging to model. - * - * @param mav - * The model - * @param tagging - * The machine tagging to add. - */ - static void addMachineTagging(ModelAndView mav, - List tagging) { - mav.addObject(MACHINE_TAGGING_OBJ, tagging); - mav.addObject(DEFAULT_TAGGING_COUNT, tagging.stream() - .filter(MachineTagging::isTaggedAsDefault).count()); - } - - /** - * Add machine reports to model. - * - * @param mav - * The model - * @param reports - * The machine reports to add. - */ - static void addMachineReports(ModelAndView mav, - Map> reports) { - mav.addObject(MACHINE_REPORTS_OBJ, reports); - } - - /** - * Add link to model. - * - * @param mav - * The model - * @param handle - * The name of the link - * @param url - * The URL to add. - */ - static void addUrl(ModelAndView mav, String handle, URI url) { - mav.addObject(handle, url); - } - - /** - * Add link to model. - * - * @param model - * The model - * @param handle - * The name of the link - * @param url - * The URL to add. - */ - static void addUrl(ModelMap model, String handle, URI url) { - model.addAttribute(handle, url); - } - - /** - * Add notice message to model. - * - * @param attrs - * The model - * @param msg - * The notice message to add. - */ - static void addNotice(RedirectAttributes attrs, String msg) { - attrs.addFlashAttribute("notice", msg); - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.admin; + +import static java.util.Collections.unmodifiableMap; + +import java.net.URI; +import java.util.List; +import java.util.Map; + +import org.springframework.ui.ModelMap; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import uk.ac.manchester.spinnaker.alloc.admin.AdminController.BlacklistData; +import uk.ac.manchester.spinnaker.alloc.admin.MachineDefinitionLoader.Machine; +import uk.ac.manchester.spinnaker.alloc.model.BoardIssueReport; +import uk.ac.manchester.spinnaker.alloc.model.BoardRecord; +import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; +import uk.ac.manchester.spinnaker.alloc.model.MachineTagging; +import uk.ac.manchester.spinnaker.alloc.model.UserRecord; +import uk.ac.manchester.spinnaker.alloc.model.GroupRecord.GroupType; +import uk.ac.manchester.spinnaker.alloc.security.TrustLevel; +import uk.ac.manchester.spinnaker.alloc.web.ControllerUtils.ViewFactory; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * Support code for {@link AdminController}. + */ +@UsedInJavadocOnly({ GroupType.class, BoardIssueReport.class }) +interface AdminControllerSupport { + // These are paths below src/main/webapp/WEB-INF/views + /** View: {@code admin/index.jsp}. */ + ViewFactory MAIN_VIEW = new ViewFactory("admin/index"); + + /** View: {@code admin/listusers.jsp}. */ + ViewFactory USER_LIST_VIEW = new ViewFactory("admin/listusers"); + + /** View: {@code admin/userdetails.jsp}. */ + ViewFactory USER_DETAILS_VIEW = new ViewFactory("admin/userdetails"); + + /** View: {@code admin/createuser.jsp}. */ + ViewFactory CREATE_USER_VIEW = new ViewFactory("admin/createuser"); + + /** View: {@code admin/listgroups.jsp}. */ + ViewFactory GROUP_LIST_VIEW = new ViewFactory("admin/listgroups"); + + /** View: {@code admin/groupdetails.jsp}. */ + ViewFactory GROUP_DETAILS_VIEW = new ViewFactory("admin/groupdetails"); + + /** View: {@code admin/creategroup.jsp}. */ + ViewFactory CREATE_GROUP_VIEW = new ViewFactory("admin/creategroup"); + + /** View: {@code admin/board.jsp}. */ + ViewFactory BOARD_VIEW = new ViewFactory("admin/board"); + + /** View: {@code admin/machine.jsp}. */ + ViewFactory MACHINE_VIEW = new ViewFactory("admin/machine"); + + /** User list in {@link #USER_LIST_VIEW}. All users. */ + String USER_LIST_OBJ = "userlist"; + + /** User list in {@link #USER_LIST_VIEW}. Local users only. */ + String LOCAL_USER_LIST_OBJ = "localusers"; + + /** User list in {@link #USER_LIST_VIEW}. OpenID users only. */ + String OPENID_USER_LIST_OBJ = "openidusers"; + + /** User details in {@link #USER_DETAILS_VIEW}. */ + String USER_OBJ = "user"; + + /** + * Group list (type: {@link GroupType#INTERNAL}) in + * {@link #GROUP_LIST_VIEW}. + */ + String LOCAL_GROUP_LIST_OBJ = "localgroups"; + + /** + * Group list (type: {@link GroupType#ORGANISATION}) in + * {@link #GROUP_LIST_VIEW}. + */ + String ORG_GROUP_LIST_OBJ = "orggroups"; + + /** + * Group list (type: {@link GroupType#COLLABRATORY}) in + * {@link #GROUP_LIST_VIEW}. + */ + String COLLAB_GROUP_LIST_OBJ = "collabgroups"; + + /** + * Group details in {@link #GROUP_DETAILS_VIEW}. Group creation info in + * {@link #CREATE_GROUP_VIEW}. + */ + String GROUP_OBJ = "group"; + + /** State in {@link #BOARD_VIEW}. {@link BoardRecord}. */ + String BOARD_OBJ = "board"; + + /** + * Blacklist data in {@link #BOARD_VIEW}. {@link BlacklistData}. + */ + String BLACKLIST_DATA_OBJ = "bldata"; + + /** + * Mapping from machine names to whether they're in service, in + * {@link #MACHINE_VIEW}. + * {@link Map}{@code <}{@link String}{@code ,}{@link Boolean}{@code >} + */ + String MACHINE_LIST_OBJ = "machineNames"; + + /** + * Machines that have been defined, in {@link #MACHINE_VIEW}. + * + * @see Machine + */ + String DEFINED_MACHINES_OBJ = "definedMachines"; + + /** + * Result of {@link MachineStateControl#getMachineTagging()}, in + * {@link #MACHINE_VIEW}. + * + * @see MachineTagging + */ + String MACHINE_TAGGING_OBJ = "machineTagging"; + + /** + * Number of {@code default} tags in {@link #MACHINE_TAGGING_OBJ}, in + * {@link #MACHINE_VIEW}. + */ + String DEFAULT_TAGGING_COUNT = "defaultCount"; + + /** + * Result of {@link MachineStateControl#getMachineReports()}, in + * {@link #MACHINE_VIEW}. + * + * @see BoardIssueReport + */ + String MACHINE_REPORTS_OBJ = "machineReports"; + + /** The base URI for the current request. In all views. */ + String BASE_URI = "baseuri"; + + /** The members of {@link TrustLevel}. In all views. */ + String TRUST_LEVELS = "trustLevels"; + + /** + * How to call {@link AdminController#listUsers() listUsers()}. In all + * views. + */ + String USERS_URI = "usersUri"; + + /** + * How to call {@link AdminController#getUserCreationForm() + * getUserCreationForm()}. In all views. + */ + String CREATE_USER_URI = "createUserUri"; + + /** + * How to call {@link AdminController#listGroups() listGroups()}. In all + * views. + */ + String GROUPS_URI = "groupsUri"; + + /** + * How to call {@link AdminController#getGroupCreationForm() + * getGroupCreationForm()}. In all views. + */ + String CREATE_GROUP_URI = "createGroupUri"; + + /** How to call {@link AdminController#boards() boards()}. In all views. */ + String BOARDS_URI = "boardsUri"; + + /** + * How to call {@link AdminController#blacklistSave(BlacklistData,ModelMap) + * blacklistSave()}, + * {@link AdminController#blacklistPush(BlacklistData, ModelMap) + * blacklistPush()}, and + * {@link AdminController#blacklistFetch(BlacklistData,ModelMap) + * blacklistFetch()}. In {@link #BOARD_VIEW}. + */ + String BLACKLIST_URI = "blacklistControlUri"; + + /** + * How to call {@link AdminController#machineManagement() + * machineManagement()}. In all views. + */ + String MACHINE_URI = "machineUri"; + + // Type-safe manipulators for models + // These are static so they *can't* access state they shouldn't + + /** + * Add local user list to model. + * + * @param mav + * The model + * @param userList + * The user list to add. + */ + static void addLocalUserList(ModelAndView mav, Map userList) { + mav.addObject(LOCAL_USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add openid-based (remote) user list to model. + * + * @param mav + * The model + * @param userList + * The user list to add. + */ + static void addRemoteUserList(ModelAndView mav, Map userList) { + mav.addObject(OPENID_USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add general user list to model. + * + * @param mav + * The model + * @param userList + * The group list to add. + */ + static void addUserList(ModelAndView mav, Map userList) { + mav.addObject(USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add user record to model. + * + * @param mav + * The model + * @param user + * The user record to add. + */ + static void addUser(ModelAndView mav, UserRecord user) { + mav.addObject(USER_OBJ, user.sanitise()); + } + + /** + * Add user record to model. + * + * @param attrs + * The model + * @param user + * The user record to add. + */ + static void addUser(RedirectAttributes attrs, UserRecord user) { + attrs.addFlashAttribute(USER_OBJ, user); + } + + /** + * Add local group list to model. + * + * @param mav + * The model + * @param groupList + * The group list to add. + */ + static void addLocalGroupList(ModelAndView mav, + Map groupList) { + mav.addObject(LOCAL_GROUP_LIST_OBJ, unmodifiableMap(groupList)); + } + + /** + * Add organisation list to model. + * + * @param mav + * The model + * @param orgList + * The group list to add. + */ + static void addOrganisationList(ModelAndView mav, + Map orgList) { + mav.addObject(ORG_GROUP_LIST_OBJ, unmodifiableMap(orgList)); + } + + /** + * Add collabratory list to model. + * + * @param mav + * The model + * @param collabList + * The group list to add. + */ + static void addCollabratoryList(ModelAndView mav, + Map collabList) { + mav.addObject(COLLAB_GROUP_LIST_OBJ, unmodifiableMap(collabList)); + } + + /** + * Add group record to model. + * + * @param mav + * The model + * @param group + * The group record to add. + */ + static void addGroup(ModelAndView mav, GroupRecord group) { + mav.addObject(GROUP_OBJ, group); + } + + /** + * Add board record to model. + * + * @param mav + * The model + * @param board + * The board record to add. + */ + static void addBoard(ModelAndView mav, BoardRecord board) { + mav.addObject(BOARD_OBJ, board); + } + + /** + * Add board record to model. + * + * @param model + * The model + * @param board + * The board record to add. + */ + static void addBoard(ModelMap model, BoardRecord board) { + model.addAttribute(BOARD_OBJ, board); + } + + /** + * Add blacklist record to model. + * + * @param model + * The model + * @param bldata + * The blacklist record to add. + */ + static void addBlacklist(ModelMap model, BlacklistData bldata) { + model.addAttribute(BLACKLIST_DATA_OBJ, bldata); + } + + /** + * Add machine list to model. + * + * @param mav + * The model + * @param machineList + * The machine list to add. + */ + static void addMachineList(ModelAndView mav, + Map machineList) { + mav.addObject(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); + } + + /** + * Add machine list to model. + * + * @param model + * The model + * @param machineList + * The machine list to add. + */ + static void addMachineList(ModelMap model, + Map machineList) { + model.addAttribute(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); + } + + /** + * Add machine tagging to model. + * + * @param mav + * The model + * @param tagging + * The machine tagging to add. + */ + static void addMachineTagging(ModelAndView mav, + List tagging) { + mav.addObject(MACHINE_TAGGING_OBJ, tagging); + mav.addObject(DEFAULT_TAGGING_COUNT, tagging.stream() + .filter(MachineTagging::isTaggedAsDefault).count()); + } + + /** + * Add machine reports to model. + * + * @param mav + * The model + * @param reports + * The machine reports to add. + */ + static void addMachineReports(ModelAndView mav, + Map> reports) { + mav.addObject(MACHINE_REPORTS_OBJ, reports); + } + + /** + * Add link to model. + * + * @param mav + * The model + * @param handle + * The name of the link + * @param url + * The URL to add. + */ + static void addUrl(ModelAndView mav, String handle, URI url) { + mav.addObject(handle, url); + } + + /** + * Add link to model. + * + * @param model + * The model + * @param handle + * The name of the link + * @param url + * The URL to add. + */ + static void addUrl(ModelMap model, String handle, URI url) { + model.addAttribute(handle, url); + } + + /** + * Add notice message to model. + * + * @param attrs + * The model + * @param msg + * The notice message to add. + */ + static void addNotice(RedirectAttributes attrs, String msg) { + attrs.addFlashAttribute("notice", msg); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java index e18f651a96..95c6bba01a 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.admin; - -import static java.util.Objects.nonNull; -import static org.slf4j.LoggerFactory.getLogger; -import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT; - -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Role; -import org.springframework.mail.MailException; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Component; - -import jakarta.annotation.PostConstruct; -import uk.ac.manchester.spinnaker.alloc.SpallocProperties; -import uk.ac.manchester.spinnaker.alloc.SpallocProperties.ReportProperties; - -/** - * Basic email sending service. - * - * @author Donal Fellows - */ -@Component -@Role(ROLE_SUPPORT) -public class ReportMailSender { - private static final Logger log = getLogger(ReportMailSender.class); - - @Autowired(required = false) - private JavaMailSender emailSender; - - @Autowired - private SpallocProperties properties; - - private ReportProperties props; - - @PostConstruct - private void getProps() { - props = properties.getReportEmail(); - } - - private static boolean haveProp(String propValue) { - return nonNull(propValue) && !propValue.isBlank(); - } - - /** - * Send an assembled message if the service is configured to do so. - *

- * NB: This call may take some time; do not hold a - * transaction open when calling this. - * - * @param email - * The message contents to send. - */ - public void sendServiceMail(Object email) { - if (nonNull(emailSender) && haveProp(props.getTo()) && props.isSend()) { - sendMessage(email.toString()); - } - } - - private void sendMessage(String body) { - var message = new SimpleMailMessage(); - if (haveProp(props.getFrom())) { - message.setFrom(props.getFrom()); - } - message.setTo(props.getTo()); - if (haveProp(props.getSubject())) { - message.setSubject(props.getSubject()); - } - message.setText(body); - try { - emailSender.send(message); - } catch (MailException e) { - log.warn("problem when sending email", e); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.admin; + +import static java.util.Objects.nonNull; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Role; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +import jakarta.annotation.PostConstruct; +import uk.ac.manchester.spinnaker.alloc.SpallocProperties; +import uk.ac.manchester.spinnaker.alloc.SpallocProperties.ReportProperties; + +/** + * Basic email sending service. + * + * @author Donal Fellows + */ +@Component +@Role(ROLE_SUPPORT) +public class ReportMailSender { + private static final Logger log = getLogger(ReportMailSender.class); + + @Autowired(required = false) + private JavaMailSender emailSender; + + @Autowired + private SpallocProperties properties; + + private ReportProperties props; + + @PostConstruct + private void getProps() { + props = properties.getReportEmail(); + } + + private static boolean haveProp(String propValue) { + return nonNull(propValue) && !propValue.isBlank(); + } + + /** + * Send an assembled message if the service is configured to do so. + *

+ * NB: This call may take some time; do not hold a + * transaction open when calling this. + * + * @param email + * The message contents to send. + */ + public void sendServiceMail(Object email) { + if (nonNull(emailSender) && haveProp(props.getTo()) && props.isSend()) { + sendMessage(email.toString()); + } + } + + private void sendMessage(String body) { + var message = new SimpleMailMessage(); + if (haveProp(props.getFrom())) { + message.setFrom(props.getFrom()); + } + message.setTo(props.getTo()); + if (haveProp(props.getSubject())) { + message.setSubject(props.getSubject()); + } + message.setText(body); + try { + emailSender.send(message); + } catch (MailException e) { + log.warn("problem when sending email", e); + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java index 1fedd7c893..4bc154ba62 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -/** - * Non-boot operations that may be performed on a BMP. - * - * @author Donal Fellows - */ -public enum BlacklistOperation { - // Careful: values must match SQL (CHECK constraints and queries) - /** Read a blacklist from a board's BMP's flash. */ - READ, - /** Write a blacklist to a board's BMP's flash. */ - WRITE, - /** Read the serial numbers from a board's BMP. */ - GET_SERIAL -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +/** + * Non-boot operations that may be performed on a BMP. + * + * @author Donal Fellows + */ +public enum BlacklistOperation { + // Careful: values must match SQL (CHECK constraints and queries) + /** Read a blacklist from a board's BMP's flash. */ + READ, + /** Write a blacklist to a board's BMP's flash. */ + WRITE, + /** Read the serial numbers from a board's BMP. */ + GET_SERIAL +} 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 1cf3015f26..79b6cf363e 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 @@ -1,201 +1,201 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -import static java.util.EnumSet.noneOf; -import static java.util.Objects.requireNonNull; -import static uk.ac.manchester.spinnaker.alloc.db.Row.enumerate; -import static uk.ac.manchester.spinnaker.alloc.db.Row.integer; -import static uk.ac.manchester.spinnaker.alloc.model.Utils.chip; - -import java.util.HashSet; -import java.util.Optional; - -import org.springframework.dao.DataAccessException; -import org.springframework.stereotype.Component; - -import com.google.errorprone.annotations.RestrictedApi; - -import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAwareBean; -import uk.ac.manchester.spinnaker.machine.Direction; -import uk.ac.manchester.spinnaker.messages.model.Blacklist; - -/** - * Read a blacklist from the database or write it to the database. This works - * with blacklists as a collection of records, not a serialised BLOB. - *

- * Arguably everything in here really ought to be in {@link Blacklist} itself, - * but that's necessarily in code that can't see into the database. - * - * @author Donal Fellows - */ -@Component -public class BlacklistStore extends DatabaseAwareBean { - /** - * Read a blacklist from the database. - * - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - public Optional readBlacklist(int boardId) { - return executeRead(conn -> readBlacklist(conn, boardId)); - } - - /** - * Read a blacklist from the database. - * - * @param conn - * The database connection. - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - private Optional readBlacklist(Connection conn, int boardId) { - try (var blChips = conn.query(GET_BLACKLISTED_CHIPS); - var blCores = conn.query(GET_BLACKLISTED_CORES); - var blLinks = conn.query(GET_BLACKLISTED_LINKS)) { - var blacklistedChips = blChips.call(boardId) - .map(chip("x", "y")).toSet(); - var blacklistedCores = blCores.call(boardId).toCollectingMap( - HashSet::new, chip("x", "y"), integer("p")); - var blacklistedLinks = blLinks.call(boardId).toCollectingMap( - () -> noneOf(Direction.class), chip("x", "y"), - enumerate("direction", Direction.class)); - - if (blacklistedChips.isEmpty() && blacklistedCores.isEmpty() - && blacklistedLinks.isEmpty()) { - return Optional.empty(); - } - return Optional.of(new Blacklist(blacklistedChips, blacklistedCores, - blacklistedLinks)); - } - } - - /** - * Save a blacklist in the database. - * - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - public void writeBlacklist(int boardId, Blacklist blacklist) { - requireNonNull(blacklist); - execute(conn -> { - writeBlacklist(conn, boardId, blacklist); - return this; // dummy - }); - } - - /** - * Save a blacklist in the database. - * - * @param conn - * Which database? - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - private void writeBlacklist(Connection conn, int boardId, - Blacklist blacklist) { - try (var clearChips = conn.update(CLEAR_BLACKLISTED_CHIPS); - var clearCores = conn.update(CLEAR_BLACKLISTED_CORES); - var clearLinks = conn.update(CLEAR_BLACKLISTED_LINKS); - var addChip = conn.update(ADD_BLACKLISTED_CHIP); - var addCore = conn.update(ADD_BLACKLISTED_CORE); - var addLink = conn.update(ADD_BLACKLISTED_LINK)) { - // TODO Keep the old blacklist data where it is the same as before - // Remove the old information - clearChips.call(boardId); - clearCores.call(boardId); - clearLinks.call(boardId); - // Write the new information - blacklist.getChips().forEach(chip -> { - addChip.call(boardId, chip.getX(), chip.getY()); - }); - blacklist.getCores().forEach((chip, cores) -> cores.forEach(c -> { - addCore.call(boardId, chip.getX(), chip.getY(), c); - })); - blacklist.getLinks().forEach((chip, links) -> links.forEach(l -> { - addLink.call(boardId, chip.getX(), chip.getY(), l); - })); - } - } - - /** - * API only exposed for testing purposes. - */ - @ForTestingOnly - interface TestAPI { - /** - * Read a blacklist from the database. - * - * @param conn - * The database connection. - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - Optional readBlacklist(Connection conn, int boardId); - - /** - * Save a blacklist in the database. - * - * @param conn - * Which database? - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - void writeBlacklist(Connection conn, int boardId, Blacklist blacklist); - } - - /** - * @return The internal API only used for testing. - * @deprecated Only use for testing, as circumvents transaction management. - */ - @Deprecated - @RestrictedApi(explanation = "just for testing", link = "index.html", - allowedOnPath = ".*/src/test/java/.*") - @ForTestingOnly - TestAPI getTestAPI() { - ForTestingOnly.Utils.checkForTestClassOnStack(); - return new TestAPI() { - @Override - public Optional readBlacklist(Connection conn, - int boardId) { - return BlacklistStore.this.readBlacklist(conn, boardId); - } - - @Override - public void writeBlacklist(Connection conn, int boardId, - Blacklist blacklist) { - BlacklistStore.this.writeBlacklist(conn, boardId, blacklist); - } - }; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +import static java.util.EnumSet.noneOf; +import static java.util.Objects.requireNonNull; +import static uk.ac.manchester.spinnaker.alloc.db.Row.enumerate; +import static uk.ac.manchester.spinnaker.alloc.db.Row.integer; +import static uk.ac.manchester.spinnaker.alloc.model.Utils.chip; + +import java.util.HashSet; +import java.util.Optional; + +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Component; + +import com.google.errorprone.annotations.RestrictedApi; + +import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAwareBean; +import uk.ac.manchester.spinnaker.machine.Direction; +import uk.ac.manchester.spinnaker.messages.model.Blacklist; + +/** + * Read a blacklist from the database or write it to the database. This works + * with blacklists as a collection of records, not a serialised BLOB. + *

+ * Arguably everything in here really ought to be in {@link Blacklist} itself, + * but that's necessarily in code that can't see into the database. + * + * @author Donal Fellows + */ +@Component +public class BlacklistStore extends DatabaseAwareBean { + /** + * Read a blacklist from the database. + * + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + public Optional readBlacklist(int boardId) { + return executeRead(conn -> readBlacklist(conn, boardId)); + } + + /** + * Read a blacklist from the database. + * + * @param conn + * The database connection. + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + private Optional readBlacklist(Connection conn, int boardId) { + try (var blChips = conn.query(GET_BLACKLISTED_CHIPS); + var blCores = conn.query(GET_BLACKLISTED_CORES); + var blLinks = conn.query(GET_BLACKLISTED_LINKS)) { + var blacklistedChips = blChips.call(boardId) + .map(chip("x", "y")).toSet(); + var blacklistedCores = blCores.call(boardId).toCollectingMap( + HashSet::new, chip("x", "y"), integer("p")); + var blacklistedLinks = blLinks.call(boardId).toCollectingMap( + () -> noneOf(Direction.class), chip("x", "y"), + enumerate("direction", Direction.class)); + + if (blacklistedChips.isEmpty() && blacklistedCores.isEmpty() + && blacklistedLinks.isEmpty()) { + return Optional.empty(); + } + return Optional.of(new Blacklist(blacklistedChips, blacklistedCores, + blacklistedLinks)); + } + } + + /** + * Save a blacklist in the database. + * + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + public void writeBlacklist(int boardId, Blacklist blacklist) { + requireNonNull(blacklist); + execute(conn -> { + writeBlacklist(conn, boardId, blacklist); + return this; // dummy + }); + } + + /** + * Save a blacklist in the database. + * + * @param conn + * Which database? + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + private void writeBlacklist(Connection conn, int boardId, + Blacklist blacklist) { + try (var clearChips = conn.update(CLEAR_BLACKLISTED_CHIPS); + var clearCores = conn.update(CLEAR_BLACKLISTED_CORES); + var clearLinks = conn.update(CLEAR_BLACKLISTED_LINKS); + var addChip = conn.update(ADD_BLACKLISTED_CHIP); + var addCore = conn.update(ADD_BLACKLISTED_CORE); + var addLink = conn.update(ADD_BLACKLISTED_LINK)) { + // TODO Keep the old blacklist data where it is the same as before + // Remove the old information + clearChips.call(boardId); + clearCores.call(boardId); + clearLinks.call(boardId); + // Write the new information + blacklist.getChips().forEach(chip -> { + addChip.call(boardId, chip.getX(), chip.getY()); + }); + blacklist.getCores().forEach((chip, cores) -> cores.forEach(c -> { + addCore.call(boardId, chip.getX(), chip.getY(), c); + })); + blacklist.getLinks().forEach((chip, links) -> links.forEach(l -> { + addLink.call(boardId, chip.getX(), chip.getY(), l); + })); + } + } + + /** + * API only exposed for testing purposes. + */ + @ForTestingOnly + interface TestAPI { + /** + * Read a blacklist from the database. + * + * @param conn + * The database connection. + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + Optional readBlacklist(Connection conn, int boardId); + + /** + * Save a blacklist in the database. + * + * @param conn + * Which database? + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + void writeBlacklist(Connection conn, int boardId, Blacklist blacklist); + } + + /** + * @return The internal API only used for testing. + * @deprecated Only use for testing, as circumvents transaction management. + */ + @Deprecated + @RestrictedApi(explanation = "just for testing", link = "index.html", + allowedOnPath = ".*/src/test/java/.*") + @ForTestingOnly + TestAPI getTestAPI() { + ForTestingOnly.Utils.checkForTestClassOnStack(); + return new TestAPI() { + @Override + public Optional readBlacklist(Connection conn, + int boardId) { + return BlacklistStore.this.readBlacklist(conn, boardId); + } + + @Override + public void writeBlacklist(Connection conn, int boardId, + Blacklist blacklist) { + BlacklistStore.this.writeBlacklist(conn, boardId, blacklist); + } + }; + } +} 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 4b29ca2d01..41bdf9975c 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 @@ -1,117 +1,117 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.function.Predicate.not; -import static org.apache.commons.io.IOUtils.buffer; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -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 - * only available in source form as labels on the boards. BMP - * identifiers can be read remotely (they come from the LPC17xx In-Application - * Programming entry point's {@code READ_SERIAL_NUMBER} call). - *

- * The original form of blacklists stores them according to their physical board - * ID because that's what is easily available during commissioning. - * - * @author Donal Fellows - */ -@Component -class PhysicalSerialMapping { - private static final Logger log = getLogger(PhysicalSerialMapping.class); - - @Value("classpath:blacklists/spin5-serial.txt") - private Resource spin5serialFile; - - private Map physicalToLogical = new HashMap<>(); - - private Map logicalToPhysical = new HashMap<>(); - - @PostConstruct - void loadMapping() throws IOException { - try (var isr = new InputStreamReader(spin5serialFile.getInputStream(), - UTF_8)) { - buffer(isr).lines().map(s -> s.replaceFirst("#.*", "").strip()) - .filter(not(String::isBlank)) - .forEach(this::parseOneMapping); - } - log.info("loaded physical/logical board ID map: {} entries", - physicalToLogical.size()); - } - - private void parseOneMapping(String line) { - var bits = line.split("\\s+", 2); - if (log.isTraceEnabled()) { - log.trace("parsing line: {}", Arrays.toString(bits)); - } - if (bits.length < 2) { - log.debug("bogus line: {}", line); - return; - } - var physical = bits[0]; - var logical = bits[1]; - var old = physicalToLogical.put(physical, logical); - if (old != null) { - log.warn("replaced mapping for {} (to {}) with {}", physical, old, - logical); - } - old = logicalToPhysical.put(logical, physical); - if (old != null) { - log.warn("replaced mapping for {} (to {}) with {}", logical, old, - physical); - } - } - - /** - * Given a BMP serial identifier, get the physical serial ID for that board. - * - * @param bmpSerialId - * The BMP serial ID. - * @return The physical board identifier, or {@code null} if the BMP serial - * ID is not recognised. - */ - public String getPhysicalId(String bmpSerialId) { - return logicalToPhysical.get(bmpSerialId); - } - - /** - * Given a physical serial identifier, get the BMP serial ID for that board. - * - * @param physicalSerialId - * The physical board serial ID. - * @return The BMP identifier, or {@code null} if the physical board serial - * ID is not recognised. - */ - public String getBMPId(String physicalSerialId) { - return physicalToLogical.get(physicalSerialId); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.function.Predicate.not; +import static org.apache.commons.io.IOUtils.buffer; +import static org.slf4j.LoggerFactory.getLogger; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +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 + * only available in source form as labels on the boards. BMP + * identifiers can be read remotely (they come from the LPC17xx In-Application + * Programming entry point's {@code READ_SERIAL_NUMBER} call). + *

+ * The original form of blacklists stores them according to their physical board + * ID because that's what is easily available during commissioning. + * + * @author Donal Fellows + */ +@Component +class PhysicalSerialMapping { + private static final Logger log = getLogger(PhysicalSerialMapping.class); + + @Value("classpath:blacklists/spin5-serial.txt") + private Resource spin5serialFile; + + private Map physicalToLogical = new HashMap<>(); + + private Map logicalToPhysical = new HashMap<>(); + + @PostConstruct + void loadMapping() throws IOException { + try (var isr = new InputStreamReader(spin5serialFile.getInputStream(), + UTF_8)) { + buffer(isr).lines().map(s -> s.replaceFirst("#.*", "").strip()) + .filter(not(String::isBlank)) + .forEach(this::parseOneMapping); + } + log.info("loaded physical/logical board ID map: {} entries", + physicalToLogical.size()); + } + + private void parseOneMapping(String line) { + var bits = line.split("\\s+", 2); + if (log.isTraceEnabled()) { + log.trace("parsing line: {}", Arrays.toString(bits)); + } + if (bits.length < 2) { + log.debug("bogus line: {}", line); + return; + } + var physical = bits[0]; + var logical = bits[1]; + var old = physicalToLogical.put(physical, logical); + if (old != null) { + log.warn("replaced mapping for {} (to {}) with {}", physical, old, + logical); + } + old = logicalToPhysical.put(logical, physical); + if (old != null) { + log.warn("replaced mapping for {} (to {}) with {}", logical, old, + physical); + } + } + + /** + * Given a BMP serial identifier, get the physical serial ID for that board. + * + * @param bmpSerialId + * The BMP serial ID. + * @return The physical board identifier, or {@code null} if the BMP serial + * ID is not recognised. + */ + public String getPhysicalId(String bmpSerialId) { + return logicalToPhysical.get(bmpSerialId); + } + + /** + * Given a physical serial identifier, get the BMP serial ID for that board. + * + * @param physicalSerialId + * The physical board serial ID. + * @return The BMP identifier, or {@code null} if the physical board serial + * ID is not recognised. + */ + public String getBMPId(String physicalSerialId) { + return physicalToLogical.get(physicalSerialId); + } +} 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 3a42204f75..7cf7edd7a4 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 @@ -1,76 +1,76 @@ -/* - * 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 - * - * http://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.compat; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -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 - * call. That means "is it a string, a boolean or a number"? Null is not - * permitted. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = { IsSaneValidator.class }) -public @interface SaneParameter { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad spalloc parameter"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} - -class IsSaneValidator implements ConstraintValidator { - @Override - public boolean isValid(Object value, ConstraintValidatorContext context) { - if (value instanceof String) { - return !((String) value).isBlank(); - } else { - return (value instanceof Boolean) || (value instanceof Number); - } - } -} +/* + * 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 + * + * http://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.compat; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +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 + * call. That means "is it a string, a boolean or a number"? Null is not + * permitted. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = { IsSaneValidator.class }) +public @interface SaneParameter { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad spalloc parameter"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} + +class IsSaneValidator implements ConstraintValidator { + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + if (value instanceof String) { + return !((String) value).isBlank(); + } else { + return (value instanceof Boolean) || (value instanceof Number); + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java index 635baded32..0766c3c542 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java @@ -1,32 +1,32 @@ -/* - * 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 - * - * http://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.compat; - -/** - * An exception that a task operation may throw. Such exceptions are converted - * into suitable classic spalloc error response messages by the service message - * handling layer. - * - * @author Donal Fellows - * @see ExceptionResponse - */ -public final class TaskException extends Exception { - private static final long serialVersionUID = 1L; - - TaskException(String msg) { - super(msg); - } -} +/* + * 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 + * + * http://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.compat; + +/** + * An exception that a task operation may throw. Such exceptions are converted + * into suitable classic spalloc error response messages by the service message + * handling layer. + * + * @author Donal Fellows + * @see ExceptionResponse + */ +public final class TaskException extends Exception { + private static final long serialVersionUID = 1L; + + TaskException(String msg) { + super(msg); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java index c49888488f..bebba94adb 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java @@ -1,649 +1,649 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.db; - -import java.io.File; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import org.springframework.core.io.Resource; -import org.springframework.dao.PermissionDeniedDataAccessException; - -import com.google.errorprone.annotations.CompileTimeConstant; -import com.google.errorprone.annotations.MustBeClosed; - -import uk.ac.manchester.spinnaker.storage.GeneratesID; -import uk.ac.manchester.spinnaker.storage.SingleRowResult; -import uk.ac.manchester.spinnaker.utils.MappableIterable; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * The primary interface to the database. It conceptually represents an SQLite - * database that can have connections opened on it. - * - * @author Donal Fellows - */ -public interface DatabaseAPI { - /** - * Get a connection. This connection is thread-bound and pooled; it must - * not be passed to other threads. They should get their own - * connections instead. The connection has auto-commit disabled; use the - * {@link Connection#transaction(DatabaseEngine.TransactedWithResult) - * transaction()} method instead. - *

- * Note that if an in-memory database is used (see - * {@link #getInMemoryDB()}), that DB can only be accessed from the - * connection returned from this method; the next call to this method - * (whether from the current thread or another one) will get an independent - * database. Such in-memory databases are not subject to thread-bound - * cleanup actions; they're simply deleted from memory when no longer used - * (but the connection should be {@code close()}d after use for efficiency - * nonetheless). - *

- * This would be marked with {@link MustBeClosed} except that causes a mess - * elsewhere. - * - * @return A configured initialised connection to the database. - */ - @MustBeClosed - Connection getConnection(); - - /** - * Create an engine interface for an in-memory database. This is intended - * mainly for testing purposes. Note that various coupled automatic services - * are disabled, in particular connections are not closed automatically. - * - * @return The in-memory database interface. - */ - DatabaseAPI getInMemoryDB(); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. - * - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be held - * at once, but only one write lock. Locks cannot be - * upgraded (because that causes deadlocks). - * @param operation - * The operation to run - * @throws RuntimeException - * If something goes wrong with the database access or the - * contained code. - */ - void executeVoid(boolean lockForWriting, Connected operation); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. This uses a write lock. - * - * @param operation - * The operation to run - * @throws RuntimeException - * If something goes wrong with the database access or the - * contained code. - */ - default void executeVoid(Connected operation) { - executeVoid(true, operation); - } - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. - * - * @param - * The type of the result of {@code operation} - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be held - * at once, but only one write lock. Locks cannot be - * upgraded (because that causes deadlocks). - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @throws RuntimeException - * If something other than database access goes wrong with the - * contained code. - */ - T execute(boolean lockForWriting, ConnectedWithResult operation); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. This uses a write lock. - * - * @param - * The type of the result of {@code operation} - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @throws RuntimeException - * If something other than database access goes wrong with the - * contained code. - */ - default T execute(ConnectedWithResult operation) { - return execute(true, operation); - } - - /** - * Creates a backup of the database. This operation should only be - * called by administrators. - * - * @param backupFilename - * The backup file to create. - */ - void createBackup(File backupFilename); - - /** - * Restores the database from backup. This operation should only be - * called by administrators. - * - * @param backupFilename - * The backup file to restore from. - * @throws PermissionDeniedDataAccessException - * If the backup cannot be read. - */ - void restoreFromBackup(File backupFilename); - - /** - * Connections made by the database engine bean. Its methods do not throw - * checked exceptions. The connection is thread-bound, and will be cleaned - * up correctly when the thread exits (ideal for thread pools). - */ - interface Connection extends AutoCloseable { - /** - * Closes this connection and releases any resources. The actual - * underlying connection may remain open if the connection pool wishes - * to maintain it, but this handle should not be retained by the caller - * after this point. - * - * @see java.sql.Connection#close() - */ - @Override - void close(); - - /** - * Undoes all changes made in the current transaction and releases any - * database locks currently held by this connection. - *

- * This method should be used only when in a transaction; it is only - * required when the transaction is to be rolled back without throwing - * an exception, as the normal behaviour of the internal transaction - * manager is to roll the transaction back when an exception leaves the - * code inside the transaction boundary. - * - * @see java.sql.Connection#rollback() - */ - void rollback(); - - /** - * Retrieves whether this connection is in read-only mode. - * - * @return {@code true} if this connection is read-only; {@code false} - * otherwise. - * @see java.sql.Connection#isReadOnly() - */ - boolean isReadOnly(); - - /** - * Whether the historical data DB is available. If it isn't, you can't - * move any data to longer-term storage, but ordinary operations should - * be fine. - * - * @return Whether the historical data DB is available. - */ - boolean isHistoricalDBAvailable(); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. - * - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be - * held at once, but only one write lock. Locks - * cannot be upgraded (because that causes - * deadlocks). - * @param operation - * The operation to run - * @see #transaction(DatabaseEngine.TransactedWithResult) - */ - void transaction(boolean lockForWriting, Transacted operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. This uses a - * write lock. - * - * @param operation - * The operation to run - * @see #transaction(DatabaseEngine.TransactedWithResult) - */ - void transaction(Transacted operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. This uses a - * write lock. - * - * @param - * The type of the result of {@code operation} - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @see #transaction(DatabaseEngine.Transacted) - */ - T transaction(TransactedWithResult operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. - * - * @param - * The type of the result of {@code operation} - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be - * held at once, but only one write lock. Locks - * cannot be upgraded (because that causes - * deadlocks). - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @see #transaction(DatabaseEngine.Transacted) - */ - T transaction(boolean lockForWriting, - TransactedWithResult operation); - - // @formatter:off - /** - * Create a new query. Usage pattern: - *

-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sql - * The SQL of the query. - * @return The query object. - * @see #query(Resource) - * @see #update(String) - * @see SQLQueries - */ - // @formatter:on - Query query(@CompileTimeConstant String sql); - - // @formatter:off - /** - * Create a new query. Usage pattern: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sql - * The SQL of the query. - * @param lockType - * Whether we expect to have a write lock. This is vital - * @return The query object. - * @see #query(Resource) - * @see #update(String) - * @see SQLQueries - */ - // @formatter:on - Query query(@CompileTimeConstant String sql, boolean lockType); - - // @formatter:off - /** - * Create a new query. - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sqlResource - * Reference to the SQL of the query. - * @return The query object. - * @see #query(String) - * @see #update(Resource) - * @see SQLQueries - */ - // @formatter:on - Query query(Resource sqlResource); - - // @formatter:off - /** - * Create a new query. - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sqlResource - * Reference to the SQL of the query. - * @param lockType - * Whether we expect to have a write lock. This is vital - * only when the query is an {@code UPDATE RETURNING}. - * @return The query object. - * @see #query(String) - * @see #update(Resource) - * @see SQLQueries - */ - // @formatter:on - Query query(Resource sqlResource, boolean lockType); - - // @formatter:off - /** - * Create a new update. Usage pattern: - *
-		 * try (var u = conn.update(SQL_UPDATE)) {
-		 *     int numRows = u.call(argument1, argument2);
-		 * }
-		 * 
- * or: - *
-		 * try (var u = conn.update(SQL_INSERT)) {
-		 *     for (var key : u.keys(argument1, argument2)) {
-		 *         // Do something with the key
-		 *     }
-		 * }
-		 * 
- * or even: - *
-		 * try (var u = conn.update(SQL_INSERT)) {
-		 *     u.key(argument1, argument2).ifPresent(key -> {
-		 *         // Do something with the key
-		 *     });
-		 * }
-		 * 
- *

- * Note: If you use a {@code RETURNING} clause then - * you should use a {@link Query} with the {@code lockType} set to - * {@code true}. - * - * @param sql - * The SQL of the update. - * @return The update object. - * @see #update(Resource) - * @see #query(String) - * @see SQLQueries - */ - // @formatter:on - Update update(@CompileTimeConstant String sql); - - // @formatter:off - /** - * Create a new update. - *

-		 * try (var u = conn.update(sqlUpdateResource)) {
-		 *     int numRows = u.call(argument1, argument2);
-		 * }
-		 * 
- * or: - *
-		 * try (var u = conn.update(sqlInsertResource)) {
-		 *     for (var key : u.keys(argument1, argument2)) {
-		 *         // Do something with the key
-		 *     }
-		 * }
-		 * 
- * or even: - *
-		 * try (var u = conn.update(sqlInsertResource)) {
-		 *     u.key(argument1, argument2).ifPresent(key -> {
-		 *         // Do something with the key
-		 *     });
-		 * }
-		 * 
- *

- * Note: If you use a {@code RETURNING} clause then - * you should use a {@link Query} with the {@code lockType} set to - * {@code true}. - * - * @param sqlResource - * Reference to the SQL of the update. - * @return The update object. - * @see #update(String) - * @see #query(Resource) - * @see SQLQueries - */ - // @formatter:on - Update update(Resource sqlResource); - } - - /** - * Some code that may be run within a transaction. - */ - @FunctionalInterface - interface Transacted { - /** - * The operation to run. - */ - void act(); - } - - /** - * Some code that may be run within a transaction that returns a result. - * - * @param - * The type of the result of the code. - */ - @FunctionalInterface - interface TransactedWithResult { - /** - * The operation to run. - * - * @return The result of the operation. - */ - T act(); - } - - /** - * Some code that may be run within a transaction and which will be given a - * new connection for the duration. - */ - @FunctionalInterface - interface Connected { - /** - * The operation to run. - * - * @param connection - * The newly-created connection. Do not save beyond the scope - * of this action. - */ - void act(Connection connection); - } - - /** - * Some code that may be run within a transaction that returns a result and - * which will be given a new connection for the duration. - * - * @param - * The type of the result of the code. - */ - @FunctionalInterface - interface ConnectedWithResult { - /** - * The operation to run. - * - * @param connection - * The newly-created connection. Do not save beyond the scope - * of this action. - * @return The result of the operation. - */ - T act(Connection connection); - } - - /** - * Common shared API between {@link Query} and {@link Update}. - * - * @author Donal Fellows - */ - interface StatementCommon extends AutoCloseable { - /** - * Get the number of arguments expected when calling this statement. - * - * @return The number of arguments. Types are arbitrary (because SQLite) - */ - int getNumArguments(); - - /** - * Get the set of names of columns produced when calling this statement. - * - * @return A set of names. The order is the order in the SQL producing - * the result set, but this should normally be insignificant. - */ - Set getRowColumnNames(); - - /** - * Close this statement. This never throws a checked exception. - */ - @Override - void close(); - - /** - * Get the query plan explanation. Note that DML and DDL may - * have empty query plans; that's up to the DB. - * - * @return A list of lines that describe the query plan. - * @see SQLite - * documentation - */ - List explainQueryPlan(); - } - - /** - * Wrapping a prepared query to be more suitable for Java 8 onwards. - * - * @author Donal Fellows - */ - interface Query extends StatementCommon { - /** - * Run the query on the given arguments. - * - * @param arguments - * Positional argument to the query - * @return The results, wrapped as a one-shot iterable. The - * {@linkplain Row rows} in the iterable must not be - * retained by callers; they may share state and might not - * outlive the iteration. - */ - MappableIterable call(Object... arguments); - - /** - * Run the query on the given arguments. The query must be one that only - * produces a single row result. - * - * @param arguments - * Positional argument to the query - * @return The single row with the results, or empty if there is no such - * row. - * @see SingleRowResult - */ - Optional call1(Object... arguments); - } - - /** - * Wrapping a prepared update to be more suitable for Java 8 onwards. - * - * @author Donal Fellows - */ - @UsedInJavadocOnly(GeneratesID.class) - interface Update extends StatementCommon { - /** - * Run the update on the given arguments. - * - * @param arguments - * Positional argument to the query - * @return The number of rows updated - */ - int call(Object... arguments); - - /** - * Run the update on the given arguments. - * - * @param arguments - * Positional arguments to the query - * @return The integer primary keys generated by the update. - * @see GeneratesID - */ - MappableIterable keys(Object... arguments); - - /** - * Run the update on the given arguments. This is expected to generate a - * single integer primary key (common with {@code INSERT}). - * - * @param arguments - * Positional arguments to the query - * @return The integer primary key generated by the update. - * @see GeneratesID - */ - Optional key(Object... arguments); - } -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.db; + +import java.io.File; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.springframework.core.io.Resource; +import org.springframework.dao.PermissionDeniedDataAccessException; + +import com.google.errorprone.annotations.CompileTimeConstant; +import com.google.errorprone.annotations.MustBeClosed; + +import uk.ac.manchester.spinnaker.storage.GeneratesID; +import uk.ac.manchester.spinnaker.storage.SingleRowResult; +import uk.ac.manchester.spinnaker.utils.MappableIterable; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * The primary interface to the database. It conceptually represents an SQLite + * database that can have connections opened on it. + * + * @author Donal Fellows + */ +public interface DatabaseAPI { + /** + * Get a connection. This connection is thread-bound and pooled; it must + * not be passed to other threads. They should get their own + * connections instead. The connection has auto-commit disabled; use the + * {@link Connection#transaction(DatabaseEngine.TransactedWithResult) + * transaction()} method instead. + *

+ * Note that if an in-memory database is used (see + * {@link #getInMemoryDB()}), that DB can only be accessed from the + * connection returned from this method; the next call to this method + * (whether from the current thread or another one) will get an independent + * database. Such in-memory databases are not subject to thread-bound + * cleanup actions; they're simply deleted from memory when no longer used + * (but the connection should be {@code close()}d after use for efficiency + * nonetheless). + *

+ * This would be marked with {@link MustBeClosed} except that causes a mess + * elsewhere. + * + * @return A configured initialised connection to the database. + */ + @MustBeClosed + Connection getConnection(); + + /** + * Create an engine interface for an in-memory database. This is intended + * mainly for testing purposes. Note that various coupled automatic services + * are disabled, in particular connections are not closed automatically. + * + * @return The in-memory database interface. + */ + DatabaseAPI getInMemoryDB(); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. + * + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be held + * at once, but only one write lock. Locks cannot be + * upgraded (because that causes deadlocks). + * @param operation + * The operation to run + * @throws RuntimeException + * If something goes wrong with the database access or the + * contained code. + */ + void executeVoid(boolean lockForWriting, Connected operation); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. This uses a write lock. + * + * @param operation + * The operation to run + * @throws RuntimeException + * If something goes wrong with the database access or the + * contained code. + */ + default void executeVoid(Connected operation) { + executeVoid(true, operation); + } + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. + * + * @param + * The type of the result of {@code operation} + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be held + * at once, but only one write lock. Locks cannot be + * upgraded (because that causes deadlocks). + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @throws RuntimeException + * If something other than database access goes wrong with the + * contained code. + */ + T execute(boolean lockForWriting, ConnectedWithResult operation); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. This uses a write lock. + * + * @param + * The type of the result of {@code operation} + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @throws RuntimeException + * If something other than database access goes wrong with the + * contained code. + */ + default T execute(ConnectedWithResult operation) { + return execute(true, operation); + } + + /** + * Creates a backup of the database. This operation should only be + * called by administrators. + * + * @param backupFilename + * The backup file to create. + */ + void createBackup(File backupFilename); + + /** + * Restores the database from backup. This operation should only be + * called by administrators. + * + * @param backupFilename + * The backup file to restore from. + * @throws PermissionDeniedDataAccessException + * If the backup cannot be read. + */ + void restoreFromBackup(File backupFilename); + + /** + * Connections made by the database engine bean. Its methods do not throw + * checked exceptions. The connection is thread-bound, and will be cleaned + * up correctly when the thread exits (ideal for thread pools). + */ + interface Connection extends AutoCloseable { + /** + * Closes this connection and releases any resources. The actual + * underlying connection may remain open if the connection pool wishes + * to maintain it, but this handle should not be retained by the caller + * after this point. + * + * @see java.sql.Connection#close() + */ + @Override + void close(); + + /** + * Undoes all changes made in the current transaction and releases any + * database locks currently held by this connection. + *

+ * This method should be used only when in a transaction; it is only + * required when the transaction is to be rolled back without throwing + * an exception, as the normal behaviour of the internal transaction + * manager is to roll the transaction back when an exception leaves the + * code inside the transaction boundary. + * + * @see java.sql.Connection#rollback() + */ + void rollback(); + + /** + * Retrieves whether this connection is in read-only mode. + * + * @return {@code true} if this connection is read-only; {@code false} + * otherwise. + * @see java.sql.Connection#isReadOnly() + */ + boolean isReadOnly(); + + /** + * Whether the historical data DB is available. If it isn't, you can't + * move any data to longer-term storage, but ordinary operations should + * be fine. + * + * @return Whether the historical data DB is available. + */ + boolean isHistoricalDBAvailable(); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. + * + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be + * held at once, but only one write lock. Locks + * cannot be upgraded (because that causes + * deadlocks). + * @param operation + * The operation to run + * @see #transaction(DatabaseEngine.TransactedWithResult) + */ + void transaction(boolean lockForWriting, Transacted operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. This uses a + * write lock. + * + * @param operation + * The operation to run + * @see #transaction(DatabaseEngine.TransactedWithResult) + */ + void transaction(Transacted operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. This uses a + * write lock. + * + * @param + * The type of the result of {@code operation} + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @see #transaction(DatabaseEngine.Transacted) + */ + T transaction(TransactedWithResult operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. + * + * @param + * The type of the result of {@code operation} + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be + * held at once, but only one write lock. Locks + * cannot be upgraded (because that causes + * deadlocks). + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @see #transaction(DatabaseEngine.Transacted) + */ + T transaction(boolean lockForWriting, + TransactedWithResult operation); + + // @formatter:off + /** + * Create a new query. Usage pattern: + *

+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sql + * The SQL of the query. + * @return The query object. + * @see #query(Resource) + * @see #update(String) + * @see SQLQueries + */ + // @formatter:on + Query query(@CompileTimeConstant String sql); + + // @formatter:off + /** + * Create a new query. Usage pattern: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sql + * The SQL of the query. + * @param lockType + * Whether we expect to have a write lock. This is vital + * @return The query object. + * @see #query(Resource) + * @see #update(String) + * @see SQLQueries + */ + // @formatter:on + Query query(@CompileTimeConstant String sql, boolean lockType); + + // @formatter:off + /** + * Create a new query. + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sqlResource + * Reference to the SQL of the query. + * @return The query object. + * @see #query(String) + * @see #update(Resource) + * @see SQLQueries + */ + // @formatter:on + Query query(Resource sqlResource); + + // @formatter:off + /** + * Create a new query. + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sqlResource + * Reference to the SQL of the query. + * @param lockType + * Whether we expect to have a write lock. This is vital + * only when the query is an {@code UPDATE RETURNING}. + * @return The query object. + * @see #query(String) + * @see #update(Resource) + * @see SQLQueries + */ + // @formatter:on + Query query(Resource sqlResource, boolean lockType); + + // @formatter:off + /** + * Create a new update. Usage pattern: + *
+		 * try (var u = conn.update(SQL_UPDATE)) {
+		 *     int numRows = u.call(argument1, argument2);
+		 * }
+		 * 
+ * or: + *
+		 * try (var u = conn.update(SQL_INSERT)) {
+		 *     for (var key : u.keys(argument1, argument2)) {
+		 *         // Do something with the key
+		 *     }
+		 * }
+		 * 
+ * or even: + *
+		 * try (var u = conn.update(SQL_INSERT)) {
+		 *     u.key(argument1, argument2).ifPresent(key -> {
+		 *         // Do something with the key
+		 *     });
+		 * }
+		 * 
+ *

+ * Note: If you use a {@code RETURNING} clause then + * you should use a {@link Query} with the {@code lockType} set to + * {@code true}. + * + * @param sql + * The SQL of the update. + * @return The update object. + * @see #update(Resource) + * @see #query(String) + * @see SQLQueries + */ + // @formatter:on + Update update(@CompileTimeConstant String sql); + + // @formatter:off + /** + * Create a new update. + *

+		 * try (var u = conn.update(sqlUpdateResource)) {
+		 *     int numRows = u.call(argument1, argument2);
+		 * }
+		 * 
+ * or: + *
+		 * try (var u = conn.update(sqlInsertResource)) {
+		 *     for (var key : u.keys(argument1, argument2)) {
+		 *         // Do something with the key
+		 *     }
+		 * }
+		 * 
+ * or even: + *
+		 * try (var u = conn.update(sqlInsertResource)) {
+		 *     u.key(argument1, argument2).ifPresent(key -> {
+		 *         // Do something with the key
+		 *     });
+		 * }
+		 * 
+ *

+ * Note: If you use a {@code RETURNING} clause then + * you should use a {@link Query} with the {@code lockType} set to + * {@code true}. + * + * @param sqlResource + * Reference to the SQL of the update. + * @return The update object. + * @see #update(String) + * @see #query(Resource) + * @see SQLQueries + */ + // @formatter:on + Update update(Resource sqlResource); + } + + /** + * Some code that may be run within a transaction. + */ + @FunctionalInterface + interface Transacted { + /** + * The operation to run. + */ + void act(); + } + + /** + * Some code that may be run within a transaction that returns a result. + * + * @param + * The type of the result of the code. + */ + @FunctionalInterface + interface TransactedWithResult { + /** + * The operation to run. + * + * @return The result of the operation. + */ + T act(); + } + + /** + * Some code that may be run within a transaction and which will be given a + * new connection for the duration. + */ + @FunctionalInterface + interface Connected { + /** + * The operation to run. + * + * @param connection + * The newly-created connection. Do not save beyond the scope + * of this action. + */ + void act(Connection connection); + } + + /** + * Some code that may be run within a transaction that returns a result and + * which will be given a new connection for the duration. + * + * @param + * The type of the result of the code. + */ + @FunctionalInterface + interface ConnectedWithResult { + /** + * The operation to run. + * + * @param connection + * The newly-created connection. Do not save beyond the scope + * of this action. + * @return The result of the operation. + */ + T act(Connection connection); + } + + /** + * Common shared API between {@link Query} and {@link Update}. + * + * @author Donal Fellows + */ + interface StatementCommon extends AutoCloseable { + /** + * Get the number of arguments expected when calling this statement. + * + * @return The number of arguments. Types are arbitrary (because SQLite) + */ + int getNumArguments(); + + /** + * Get the set of names of columns produced when calling this statement. + * + * @return A set of names. The order is the order in the SQL producing + * the result set, but this should normally be insignificant. + */ + Set getRowColumnNames(); + + /** + * Close this statement. This never throws a checked exception. + */ + @Override + void close(); + + /** + * Get the query plan explanation. Note that DML and DDL may + * have empty query plans; that's up to the DB. + * + * @return A list of lines that describe the query plan. + * @see SQLite + * documentation + */ + List explainQueryPlan(); + } + + /** + * Wrapping a prepared query to be more suitable for Java 8 onwards. + * + * @author Donal Fellows + */ + interface Query extends StatementCommon { + /** + * Run the query on the given arguments. + * + * @param arguments + * Positional argument to the query + * @return The results, wrapped as a one-shot iterable. The + * {@linkplain Row rows} in the iterable must not be + * retained by callers; they may share state and might not + * outlive the iteration. + */ + MappableIterable call(Object... arguments); + + /** + * Run the query on the given arguments. The query must be one that only + * produces a single row result. + * + * @param arguments + * Positional argument to the query + * @return The single row with the results, or empty if there is no such + * row. + * @see SingleRowResult + */ + Optional call1(Object... arguments); + } + + /** + * Wrapping a prepared update to be more suitable for Java 8 onwards. + * + * @author Donal Fellows + */ + @UsedInJavadocOnly(GeneratesID.class) + interface Update extends StatementCommon { + /** + * Run the update on the given arguments. + * + * @param arguments + * Positional argument to the query + * @return The number of rows updated + */ + int call(Object... arguments); + + /** + * Run the update on the given arguments. + * + * @param arguments + * Positional arguments to the query + * @return The integer primary keys generated by the update. + * @see GeneratesID + */ + MappableIterable keys(Object... arguments); + + /** + * Run the update on the given arguments. This is expected to generate a + * single integer primary key (common with {@code INSERT}). + * + * @param arguments + * Positional arguments to the query + * @return The integer primary key generated by the update. + * @see GeneratesID + */ + Optional key(Object... arguments); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java index 560c2f5f6e..0df05f40b9 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2022 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 - * - * http://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 java.util.function.Function; - -import uk.ac.manchester.spinnaker.alloc.db.Row; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** Miscellaneous utilities. */ -public abstract class Utils { - private Utils() { - } - - /** - * Extract a chip from a result set row. - * - * @param row - * The row to extract from. - * @param x - * The name of the column with the X coordinate. - * @param y - * The name of the column with the Y coordinate. - * @return The chip location. - */ - public static ChipLocation chip(Row row, String x, String y) { - return new ChipLocation(row.getInt(x), row.getInt(y)); - } - - /** - * Create a function for extracting a chip from a result set row. - * - * @param x - * The name of the column with the X coordinate. - * @param y - * The name of the column with the Y coordinate. - * @return The mapping function. - */ - public static Function chip(String x, String y) { - return row -> new ChipLocation(row.getInt(x), row.getInt(y)); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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 java.util.function.Function; + +import uk.ac.manchester.spinnaker.alloc.db.Row; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** Miscellaneous utilities. */ +public abstract class Utils { + private Utils() { + } + + /** + * Extract a chip from a result set row. + * + * @param row + * The row to extract from. + * @param x + * The name of the column with the X coordinate. + * @param y + * The name of the column with the Y coordinate. + * @return The chip location. + */ + public static ChipLocation chip(Row row, String x, String y) { + return new ChipLocation(row.getInt(x), row.getInt(y)); + } + + /** + * Create a function for extracting a chip from a result set row. + * + * @param x + * The name of the column with the X coordinate. + * @param y + * The name of the column with the Y coordinate. + * @return The mapping function. + */ + public static Function chip(String x, String y) { + return row -> new ChipLocation(row.getInt(x), row.getInt(y)); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java index fd271f8484..1d68e38725 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java @@ -1,100 +1,100 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.security; - -import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SUB; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL_VERIFIED; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.NAME; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME; - -import java.util.Objects; -import java.util.Optional; - -import org.springframework.security.oauth2.core.user.OAuth2User; - -/** - * An object that can say something about what user it was derived from. Note - * that you never have both the user information and the token at the same time, - * but they contain fairly similar contents. - */ -public interface OpenIDUserAware { - /** - * Get the underlying OpenID user information. - * - * @return The user info, if known. Pay attention to the attributes. - */ - Optional getOpenIdUser(); - - /** - * Get a claim/attribute that is a string. - * - * @param claimName - * The name of the claim. - * @return The string. - * @throws IllegalStateException - * If {@link #getOpenIdUser()} doesn't provide anything we can - * get claims from. - */ - default String getStringClaim(String claimName) { - return getOpenIdUser() - .map(u -> Objects.toString(u.getAttribute(claimName))) - .orElseThrow(() -> new IllegalStateException( - "no user or token to supply claim")); - } - - /** - * @return The OpenID subject identifier. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdSubject() { - return getStringClaim(SUB); - } - - /** - * @return The preferred OpenID user name. We don't use this - * directly as it may clash with other user names. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdUserName() { - return getStringClaim(PREFERRED_USERNAME); - } - - /** - * @return The real name of the OpenID user. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdName() { - return getStringClaim(NAME); - } - - /** - * @return The verified email address of the OpenID user, if available. - */ - default Optional getOpenIdEmail() { - var email = getOpenIdUser().map(uu -> uu.getAttributes()) - .filter(uu -> uu.containsKey(EMAIL_VERIFIED) - && (Boolean) uu.get(EMAIL_VERIFIED)) - .map(uu -> uu.get(EMAIL).toString()); - if (email.isPresent()) { - return email; - } - return null; - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.security; + +import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SUB; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL_VERIFIED; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.NAME; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME; + +import java.util.Objects; +import java.util.Optional; + +import org.springframework.security.oauth2.core.user.OAuth2User; + +/** + * An object that can say something about what user it was derived from. Note + * that you never have both the user information and the token at the same time, + * but they contain fairly similar contents. + */ +public interface OpenIDUserAware { + /** + * Get the underlying OpenID user information. + * + * @return The user info, if known. Pay attention to the attributes. + */ + Optional getOpenIdUser(); + + /** + * Get a claim/attribute that is a string. + * + * @param claimName + * The name of the claim. + * @return The string. + * @throws IllegalStateException + * If {@link #getOpenIdUser()} doesn't provide anything we can + * get claims from. + */ + default String getStringClaim(String claimName) { + return getOpenIdUser() + .map(u -> Objects.toString(u.getAttribute(claimName))) + .orElseThrow(() -> new IllegalStateException( + "no user or token to supply claim")); + } + + /** + * @return The OpenID subject identifier. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdSubject() { + return getStringClaim(SUB); + } + + /** + * @return The preferred OpenID user name. We don't use this + * directly as it may clash with other user names. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdUserName() { + return getStringClaim(PREFERRED_USERNAME); + } + + /** + * @return The real name of the OpenID user. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdName() { + return getStringClaim(NAME); + } + + /** + * @return The verified email address of the OpenID user, if available. + */ + default Optional getOpenIdEmail() { + var email = getOpenIdUser().map(uu -> uu.getAttributes()) + .filter(uu -> uu.containsKey(EMAIL_VERIFIED) + && (Boolean) uu.get(EMAIL_VERIFIED)) + .map(uu -> uu.get(EMAIL).toString()); + if (email.isPresent()) { + return email; + } + return null; + } +} diff --git a/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json index b528a414f6..2e45818e2a 100644 --- a/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -15,4 +15,4 @@ "description": "Comma-separated list (in a string) of package names to scan." } ] -} \ No newline at end of file +} 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 b69462c699..e186508c7e 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 @@ -1,185 +1,185 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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; - -import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; -import uk.ac.manchester.spinnaker.storage.GeneratesID; -import uk.ac.manchester.spinnaker.storage.Parameter; -import uk.ac.manchester.spinnaker.storage.ResultColumn; -import uk.ac.manchester.spinnaker.storage.SingleRowResult; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * SQL queries for testing purposes. - * - * @see SQLQueries - */ -@UsedInJavadocOnly(SQLQueries.class) -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 (?, ?)"; - - /** 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 (?, ?, ?, ?)"; - - /** 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 (?, ?)"; - - /** Count the jobs. */ - @ResultColumn("cnt") - @SingleRowResult - 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"; - - /** Count the active power change requests. */ - @ResultColumn("cnt") - @SingleRowResult - String TEST_COUNT_POWER_CHANGES = - "SELECT COUNT(*) AS cnt FROM pending_changes"; - - /** 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"; - - /** 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"; - - /** 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 machine_id = ? AND user_id = ?"; - - /** Set the quota for a group. */ - @Parameter("quota") - @Parameter("group") - String TEST_SET_QUOTA = - "UPDATE groups SET quota = :quota WHERE group_id = :group"; - - /** Create a machine, specifying the ID. */ - @Parameter("machine_id") - @Parameter("machine_name") - @Parameter("width") - @Parameter("height") - @Parameter("depth") - @GeneratesID - String INSERT_MACHINE = - "INSERT OR IGNORE INTO machines(machine_id, machine_name, " - + "width, height, [depth], board_model) " - + "VALUES (?, ?, ?, ?, ?, 5)"; - - /** Create a BMP, specifying the ID. */ - @Parameter("bmp_id") - @Parameter("machine_id") - @Parameter("address") - @Parameter("cabinet") - @Parameter("frame") - @GeneratesID - String INSERT_BMP_WITH_ID = - "INSERT OR IGNORE INTO bmp(bmp_id, machine_id, address, " - + "cabinet, frame) VALUES (?, ?, ?, ?, ?)"; - - /** Create a user, specifying the ID. */ - @Parameter("user_id") - @Parameter("user_name") - @Parameter("trust_level") - @Parameter("disabled") - @GeneratesID - String INSERT_USER = "INSERT OR IGNORE 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 OR IGNORE INTO " - + "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 OR IGNORE INTO group_memberships(" - + "membership_id, user_id, group_id) VALUES (?, ?, ?)"; - - /** Create a board, specifying the ID. */ - @Parameter("board_id") - @Parameter("address") - @Parameter("bmp_id") - @Parameter("board_num") - @Parameter("machine_id") - @Parameter("x") - @Parameter("y") - @Parameter("z") - @Parameter("root_x") - @Parameter("root_y") - @Parameter("board_power") - @GeneratesID - String INSERT_BOARD_WITH_ID = - "INSERT OR IGNORE 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") - @Parameter("owner") - @Parameter("group_id") - @Parameter("root_id") - @Parameter("job_state") - @Parameter("create_timestamp") - @Parameter("allocation_timestamp") - @Parameter("death_timestamp") - @Parameter("allocation_size") - @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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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; + +import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; +import uk.ac.manchester.spinnaker.storage.GeneratesID; +import uk.ac.manchester.spinnaker.storage.Parameter; +import uk.ac.manchester.spinnaker.storage.ResultColumn; +import uk.ac.manchester.spinnaker.storage.SingleRowResult; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * SQL queries for testing purposes. + * + * @see SQLQueries + */ +@UsedInJavadocOnly(SQLQueries.class) +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 (?, ?)"; + + /** 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 (?, ?, ?, ?)"; + + /** 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 (?, ?)"; + + /** Count the jobs. */ + @ResultColumn("cnt") + @SingleRowResult + 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"; + + /** Count the active power change requests. */ + @ResultColumn("cnt") + @SingleRowResult + String TEST_COUNT_POWER_CHANGES = + "SELECT COUNT(*) AS cnt FROM pending_changes"; + + /** 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"; + + /** 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"; + + /** 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 machine_id = ? AND user_id = ?"; + + /** Set the quota for a group. */ + @Parameter("quota") + @Parameter("group") + String TEST_SET_QUOTA = + "UPDATE groups SET quota = :quota WHERE group_id = :group"; + + /** Create a machine, specifying the ID. */ + @Parameter("machine_id") + @Parameter("machine_name") + @Parameter("width") + @Parameter("height") + @Parameter("depth") + @GeneratesID + String INSERT_MACHINE = + "INSERT OR IGNORE INTO machines(machine_id, machine_name, " + + "width, height, [depth], board_model) " + + "VALUES (?, ?, ?, ?, ?, 5)"; + + /** Create a BMP, specifying the ID. */ + @Parameter("bmp_id") + @Parameter("machine_id") + @Parameter("address") + @Parameter("cabinet") + @Parameter("frame") + @GeneratesID + String INSERT_BMP_WITH_ID = + "INSERT OR IGNORE INTO bmp(bmp_id, machine_id, address, " + + "cabinet, frame) VALUES (?, ?, ?, ?, ?)"; + + /** Create a user, specifying the ID. */ + @Parameter("user_id") + @Parameter("user_name") + @Parameter("trust_level") + @Parameter("disabled") + @GeneratesID + String INSERT_USER = "INSERT OR IGNORE 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 OR IGNORE INTO " + + "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 OR IGNORE INTO group_memberships(" + + "membership_id, user_id, group_id) VALUES (?, ?, ?)"; + + /** Create a board, specifying the ID. */ + @Parameter("board_id") + @Parameter("address") + @Parameter("bmp_id") + @Parameter("board_num") + @Parameter("machine_id") + @Parameter("x") + @Parameter("y") + @Parameter("z") + @Parameter("root_x") + @Parameter("root_y") + @Parameter("board_power") + @GeneratesID + String INSERT_BOARD_WITH_ID = + "INSERT OR IGNORE 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") + @Parameter("owner") + @Parameter("group_id") + @Parameter("root_id") + @Parameter("job_state") + @Parameter("create_timestamp") + @Parameter("allocation_timestamp") + @Parameter("death_timestamp") + @Parameter("allocation_size") + @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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; +} 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 f0eec34188..cdacaad548 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 @@ -1,530 +1,530 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import static java.nio.file.Files.delete; -import static java.nio.file.Files.exists; -import static java.time.Duration.ofSeconds; -import static java.time.Instant.now; -import static java.time.Instant.ofEpochMilli; -import static java.time.Instant.ofEpochSecond; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.slf4j.LoggerFactory.getLogger; -import static uk.ac.manchester.spinnaker.alloc.db.Row.string; -import static uk.ac.manchester.spinnaker.alloc.model.JobState.DESTROYED; -import static uk.ac.manchester.spinnaker.alloc.model.JobState.QUEUED; -import static uk.ac.manchester.spinnaker.alloc.security.TrustLevel.BASIC; - -import java.io.IOException; -import java.nio.file.Paths; -import java.time.Duration; -import java.time.Instant; -import java.util.Collection; -import java.util.List; -import java.util.function.IntConsumer; -import java.util.function.ObjIntConsumer; - -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataAccessException; -import org.springframework.lang.NonNull; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; - -import uk.ac.manchester.spinnaker.alloc.db.DatabaseEngine; -import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connected; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Transacted; -import uk.ac.manchester.spinnaker.alloc.model.JobState; -import uk.ac.manchester.spinnaker.alloc.security.Permit; - -@SuppressWarnings({ - "checkstyle:ParameterNumber", "checkstyle:VisibilityModifier" -}) -public abstract class TestSupport extends SQLQueries implements SupportQueries { - /** Bring in the application Spring configuration that we're testing. */ - @Configuration - @ComponentScan(basePackageClasses = SpallocProperties.class) - public static class Config { - } - - protected static final Logger log = getLogger(TestSupport.class); - - /** Machine ID. */ - protected static final int MACHINE = 1000; - - /** Machine name. */ - protected static final String MACHINE_NAME = "foo_machine"; - - /** BMP ID. */ - protected static final int BMP = 2000; - - /** BMP IP address. */ - protected static final String BMP_ADDR = "1.1.1.1"; - - /** Board ID. */ - protected static final int BOARD = 3000; - - /** Board IP address. */ - protected static final String BOARD_ADDR = "2.2.2.2"; - - /** User ID. */ - protected static final int USER = 4000; - - /** User name. */ - public static final String USER_NAME = "user_bar"; - - /** Group ID. */ - protected static final int GROUP = 5000; - - /** Group name. */ - public static final String GROUP_NAME = "grill"; - - /** User-group membership ID. */ - protected static final int MEMBERSHIP = 6000; - - /** Initial quota. */ - protected static final long INITIAL_QUOTA = 1024; - - /** The DB. */ - @Autowired - protected DatabaseEngine db; - - /** The context connection to the DB. */ - protected Connection conn; - - /** - * Delete a DB file. It must not be open! - * - * @param dbPath - * Where the DB is. - * @throws IOException - * On failure. - */ - protected static void killDB(String dbPath) throws IOException { - var dbp = Paths.get(dbPath); - if (exists(dbp)) { - log.info("deleting old database: {}", dbp); - delete(dbp); - } - } - - 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); - } - try (var u = c.update(INSERT_BMP_WITH_ID)) { - u.call(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); - } - try (var u = c.update(INSERT_GROUP)) { - u.call(GROUP, GROUP_NAME, INITIAL_QUOTA); - } - try (var u = c.update(INSERT_MEMBER)) { - u.call(MEMBERSHIP, USER, GROUP); - } - } - - /** - * Set up a machine with one board, and a user. - */ - protected void setupDB1() { - try (var c = db.getConnection()) { - c.transaction(() -> setupDB1(c)); - } - } - - private static void setupDB1(Connection c) { - // A simple machine - makeMachine(c, 1, 1, 1); - // Add one board to the machine - try (var u = c.update(INSERT_BOARD_WITH_ID)) { - u.call(BOARD, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0, 0, 0, false); - } - // A disabled permission-less user with a quota - makeUser(c); - } - - /** - * Set up a machine with three boards, and a user. - */ - protected void setupDB3() { - try (var c = db.getConnection()) { - c.transaction(() -> setupDB3(c)); - } - } - - private static void setupDB3(Connection c) { - // A simple machine - makeMachine(c, 1, 1, 3); - // 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); - } - try (var u = c.update(INSERT_LINK)) { - u.call(b0, 0, b1, 3, true); - u.call(b0, 1, b2, 4, true); - u.call(b1, 2, b2, 5, true); - } - // A disabled permission-less user with a quota - makeUser(c); - } - - /** - * Insert a job of a given size and length. - * - * @param c - * DB connection - * @param root - * Root board, or {@code null} - * @param state - * Job state - * @param size - * Number of boards, or {@code null} - * @param createTime - * Time of creation, or {@code null} - * @param allocateTime - * Time of allocation, or {@code null} - * @param deathTime - * Time of death, or {@code null} - * @param keepalive - * Keepalive interval, or {@code null} - * @param keepaliveTime - * Time of last keepalive, or {@code null} - * @return Job ID - */ - protected static int makeJob(Connection c, Integer root, - @NonNull JobState state, Integer size, Instant createTime, - Instant allocateTime, Instant deathTime, Duration keepalive, - Instant keepaliveTime) { - try (var u = c.update(INSERT_JOB_WITH_TIMESTAMPS)) { - return u.key(MACHINE, USER, GROUP, root, state, createTime, - allocateTime, deathTime, size, keepalive, keepaliveTime) - .orElseThrow( - () -> new RuntimeException("failed to insert job")); - } - } - - /** - * Insert a dead job of a given size and length. - * - * @param c - * DB connection - * @param size - * Number of boards - * @param time - * Length of time (seconds) - * @return Job ID - */ - protected static int makeFinishedJob(Connection c, int size, int time) { - return makeJob(c, BOARD, DESTROYED, size, ofEpochSecond(0), - ofEpochSecond(time), ofEpochSecond(time + time), - ofSeconds(time), null); - } - - /** - * Directly manipulate the allocation. - * - * @param c - * DB connection - * @param boardId - * What board are we changing - * @param jobId - * What job are we assigning - */ - 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")) { - u.call(jobId, boardId); - } - } - - /** - * Directly manipulate the reverse of the allocation (root only). - * - * @param c - * DB connection - * @param jobId - * What job are we changing - * @param boardId - * What board are we assigning as the root - */ - 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")) { - u.call(boardId, jobId); - } - } - - protected List getReports() { - return db.execute(c -> { - try (var q = c.query("SELECT reported_issue FROM board_reports")) { - return q.call().map(string("reported_issue")).toList(); - } - }); - } - - protected void killReports() { - db.executeVoid(c -> { - try (var u = c.update("DELETE from board_reports")) { - u.call(); - } - }); - } - - protected void checkAndRollback(Connected act) { - db.executeVoid(c -> { - try { - conn = c; - act.act(c); - } finally { - c.rollback(); - } - }); - } - - protected void doTransactionalTest(Transacted action) { - try (var c = db.getConnection()) { - c.transaction(() -> { - try { - conn = c; - action.act(); - } finally { - try { - c.rollback(); - } catch (DataAccessException ignored) { - log.trace("ignoring DAE from rollback", ignored); - } - conn = null; - } - }); - } - } - - /** - * Insert a live job. Needs a matching allocation request. - * - * @param time - * Length of time for keepalive (seconds) - * @return Job ID - */ - protected int makeQueuedJob(int time) { - return makeJob(conn, null, QUEUED, null, ofEpochMilli(0), null, null, - ofSeconds(time), now()); - } - - protected void makeAllocBySizeRequest(int job, int size) { - try (var u = conn.update(TEST_INSERT_REQ_SIZE)) { - conn.transaction(() -> u.call(job, size)); - } - } - - protected void makeAllocByDimensionsRequest(int job, int width, int height, - int allowedDead) { - try (var u = conn.update(TEST_INSERT_REQ_DIMS)) { - conn.transaction(() -> u.call(job, width, height, allowedDead)); - } - } - - protected void makeAllocByBoardIdRequest(int job, int board) { - try (var u = conn.update(TEST_INSERT_REQ_BOARD)) { - conn.transaction(() -> u.call(job, board)); - } - } - - protected JobState getJobState(int job) { - try (var q = conn.query(GET_JOB)) { - return conn.transaction(() -> q.call1(job).orElseThrow() - .getEnum("job_state", JobState.class)); - } - } - - protected int getJobRequestCount() { - try (var q = conn.query(TEST_COUNT_REQUESTS)) { - return conn.transaction( - () -> q.call1(QUEUED).orElseThrow().getInt("cnt")); - } - } - - protected int getPendingPowerChanges() { - try (var q = conn.query(TEST_COUNT_POWER_CHANGES)) { - return conn - .transaction(() -> q.call1().orElseThrow().getInt("cnt")); - } - } - - // Wrappers for temporarily putting the DB into a state with a job/alloc - - protected int makeJob() { - return db.execute(c -> makeJob(c, null, QUEUED, null, - ofEpochMilli(0), null, null, ofSeconds(0), now())); - } - - protected void withJob(IntConsumer act) { - int jobId = makeJob(); - try { - act.accept(jobId); - } finally { - nukeJob(jobId); - } - } - - protected void nukeJob(int jobId) { - db.executeVoid(c -> { - try (var u = c.update("DELETE FROM jobs WHERE job_id = ?")) { - u.call(jobId); - } - }); - } - - protected void withAllocation(int jobId, Runnable act) { - db.executeVoid(c -> { - allocateBoardToJob(c, BOARD, jobId); - setAllocRoot(c, jobId, BOARD); - }); - try { - act.run(); - } finally { - db.executeVoid(c -> { - allocateBoardToJob(c, BOARD, null); - setAllocRoot(c, jobId, null); - }); - } - } - - protected void withStandardAllocatedJob(ObjIntConsumer act) { - // Composite op, for brevity - withJob(jobId -> inContext(c -> withAllocation(jobId, - () -> act.accept(c.setAuth(USER_NAME), jobId)))); - } - - private static final int DELAY_MS = 1000; - - /** Sleep for one second. */ - protected static void snooze1s() { - try { - Thread.sleep(DELAY_MS); - } catch (InterruptedException e) { - assumeTrue(false, "sleep() was interrupted"); - } - } - - /** Capability provided by {@link #inContext(InC)} to what it guards. */ - public interface C { - /** - * Install an authentication token. - * - * @param auth - * The authentication token to install. {@code null} to - * remove. - */ - void setAuth(Authentication auth); - - /** - * Install the named user as the current user and provide a permit that - * allows that user to touch resources. - * - * @param name - * The user name. - * @return The newly-minted permit. - */ - default Permit setAuth(String name) { - @SuppressWarnings("serial") - var a = new Authentication() { - @Override - public String getName() { - return name; - } - - @Override - public Collection getAuthorities() { - return List.of(); - } - - @Override - public Object getCredentials() { - return null; - } - - @Override - public Object getDetails() { - return null; - } - - @Override - public Object getPrincipal() { - return null; - } - - @Override - public boolean isAuthenticated() { - return true; - } - - @Override - public void setAuthenticated(boolean isAuthenticated) { - } - }; - setAuth(a); - return new Permit(SecurityContextHolder.getContext()); - } - } - - /** - * An action wrapped by {@link #inContext(InC)}. - */ - public interface InC { - /** - * The wrapped action. - * - * @param c - * The capability to set the current user. - */ - void act(C c); - } - - /** - * Run code with the capability to set the current user. Will clean up - * afterwards. - * - * @param inc - * The code to run. - */ - public static void inContext(InC inc) { - var context = SecurityContextHolder.getContext(); - try { - inc.act(context::setAuthentication); - } finally { - context.setAuthentication(null); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import static java.nio.file.Files.delete; +import static java.nio.file.Files.exists; +import static java.time.Duration.ofSeconds; +import static java.time.Instant.now; +import static java.time.Instant.ofEpochMilli; +import static java.time.Instant.ofEpochSecond; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.slf4j.LoggerFactory.getLogger; +import static uk.ac.manchester.spinnaker.alloc.db.Row.string; +import static uk.ac.manchester.spinnaker.alloc.model.JobState.DESTROYED; +import static uk.ac.manchester.spinnaker.alloc.model.JobState.QUEUED; +import static uk.ac.manchester.spinnaker.alloc.security.TrustLevel.BASIC; + +import java.io.IOException; +import java.nio.file.Paths; +import java.time.Duration; +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.function.IntConsumer; +import java.util.function.ObjIntConsumer; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.DataAccessException; +import org.springframework.lang.NonNull; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; + +import uk.ac.manchester.spinnaker.alloc.db.DatabaseEngine; +import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connected; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Transacted; +import uk.ac.manchester.spinnaker.alloc.model.JobState; +import uk.ac.manchester.spinnaker.alloc.security.Permit; + +@SuppressWarnings({ + "checkstyle:ParameterNumber", "checkstyle:VisibilityModifier" +}) +public abstract class TestSupport extends SQLQueries implements SupportQueries { + /** Bring in the application Spring configuration that we're testing. */ + @Configuration + @ComponentScan(basePackageClasses = SpallocProperties.class) + public static class Config { + } + + protected static final Logger log = getLogger(TestSupport.class); + + /** Machine ID. */ + protected static final int MACHINE = 1000; + + /** Machine name. */ + protected static final String MACHINE_NAME = "foo_machine"; + + /** BMP ID. */ + protected static final int BMP = 2000; + + /** BMP IP address. */ + protected static final String BMP_ADDR = "1.1.1.1"; + + /** Board ID. */ + protected static final int BOARD = 3000; + + /** Board IP address. */ + protected static final String BOARD_ADDR = "2.2.2.2"; + + /** User ID. */ + protected static final int USER = 4000; + + /** User name. */ + public static final String USER_NAME = "user_bar"; + + /** Group ID. */ + protected static final int GROUP = 5000; + + /** Group name. */ + public static final String GROUP_NAME = "grill"; + + /** User-group membership ID. */ + protected static final int MEMBERSHIP = 6000; + + /** Initial quota. */ + protected static final long INITIAL_QUOTA = 1024; + + /** The DB. */ + @Autowired + protected DatabaseEngine db; + + /** The context connection to the DB. */ + protected Connection conn; + + /** + * Delete a DB file. It must not be open! + * + * @param dbPath + * Where the DB is. + * @throws IOException + * On failure. + */ + protected static void killDB(String dbPath) throws IOException { + var dbp = Paths.get(dbPath); + if (exists(dbp)) { + log.info("deleting old database: {}", dbp); + delete(dbp); + } + } + + 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); + } + try (var u = c.update(INSERT_BMP_WITH_ID)) { + u.call(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); + } + try (var u = c.update(INSERT_GROUP)) { + u.call(GROUP, GROUP_NAME, INITIAL_QUOTA); + } + try (var u = c.update(INSERT_MEMBER)) { + u.call(MEMBERSHIP, USER, GROUP); + } + } + + /** + * Set up a machine with one board, and a user. + */ + protected void setupDB1() { + try (var c = db.getConnection()) { + c.transaction(() -> setupDB1(c)); + } + } + + private static void setupDB1(Connection c) { + // A simple machine + makeMachine(c, 1, 1, 1); + // Add one board to the machine + try (var u = c.update(INSERT_BOARD_WITH_ID)) { + u.call(BOARD, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0, 0, 0, false); + } + // A disabled permission-less user with a quota + makeUser(c); + } + + /** + * Set up a machine with three boards, and a user. + */ + protected void setupDB3() { + try (var c = db.getConnection()) { + c.transaction(() -> setupDB3(c)); + } + } + + private static void setupDB3(Connection c) { + // A simple machine + makeMachine(c, 1, 1, 3); + // 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); + } + try (var u = c.update(INSERT_LINK)) { + u.call(b0, 0, b1, 3, true); + u.call(b0, 1, b2, 4, true); + u.call(b1, 2, b2, 5, true); + } + // A disabled permission-less user with a quota + makeUser(c); + } + + /** + * Insert a job of a given size and length. + * + * @param c + * DB connection + * @param root + * Root board, or {@code null} + * @param state + * Job state + * @param size + * Number of boards, or {@code null} + * @param createTime + * Time of creation, or {@code null} + * @param allocateTime + * Time of allocation, or {@code null} + * @param deathTime + * Time of death, or {@code null} + * @param keepalive + * Keepalive interval, or {@code null} + * @param keepaliveTime + * Time of last keepalive, or {@code null} + * @return Job ID + */ + protected static int makeJob(Connection c, Integer root, + @NonNull JobState state, Integer size, Instant createTime, + Instant allocateTime, Instant deathTime, Duration keepalive, + Instant keepaliveTime) { + try (var u = c.update(INSERT_JOB_WITH_TIMESTAMPS)) { + return u.key(MACHINE, USER, GROUP, root, state, createTime, + allocateTime, deathTime, size, keepalive, keepaliveTime) + .orElseThrow( + () -> new RuntimeException("failed to insert job")); + } + } + + /** + * Insert a dead job of a given size and length. + * + * @param c + * DB connection + * @param size + * Number of boards + * @param time + * Length of time (seconds) + * @return Job ID + */ + protected static int makeFinishedJob(Connection c, int size, int time) { + return makeJob(c, BOARD, DESTROYED, size, ofEpochSecond(0), + ofEpochSecond(time), ofEpochSecond(time + time), + ofSeconds(time), null); + } + + /** + * Directly manipulate the allocation. + * + * @param c + * DB connection + * @param boardId + * What board are we changing + * @param jobId + * What job are we assigning + */ + 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")) { + u.call(jobId, boardId); + } + } + + /** + * Directly manipulate the reverse of the allocation (root only). + * + * @param c + * DB connection + * @param jobId + * What job are we changing + * @param boardId + * What board are we assigning as the root + */ + 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")) { + u.call(boardId, jobId); + } + } + + protected List getReports() { + return db.execute(c -> { + try (var q = c.query("SELECT reported_issue FROM board_reports")) { + return q.call().map(string("reported_issue")).toList(); + } + }); + } + + protected void killReports() { + db.executeVoid(c -> { + try (var u = c.update("DELETE from board_reports")) { + u.call(); + } + }); + } + + protected void checkAndRollback(Connected act) { + db.executeVoid(c -> { + try { + conn = c; + act.act(c); + } finally { + c.rollback(); + } + }); + } + + protected void doTransactionalTest(Transacted action) { + try (var c = db.getConnection()) { + c.transaction(() -> { + try { + conn = c; + action.act(); + } finally { + try { + c.rollback(); + } catch (DataAccessException ignored) { + log.trace("ignoring DAE from rollback", ignored); + } + conn = null; + } + }); + } + } + + /** + * Insert a live job. Needs a matching allocation request. + * + * @param time + * Length of time for keepalive (seconds) + * @return Job ID + */ + protected int makeQueuedJob(int time) { + return makeJob(conn, null, QUEUED, null, ofEpochMilli(0), null, null, + ofSeconds(time), now()); + } + + protected void makeAllocBySizeRequest(int job, int size) { + try (var u = conn.update(TEST_INSERT_REQ_SIZE)) { + conn.transaction(() -> u.call(job, size)); + } + } + + protected void makeAllocByDimensionsRequest(int job, int width, int height, + int allowedDead) { + try (var u = conn.update(TEST_INSERT_REQ_DIMS)) { + conn.transaction(() -> u.call(job, width, height, allowedDead)); + } + } + + protected void makeAllocByBoardIdRequest(int job, int board) { + try (var u = conn.update(TEST_INSERT_REQ_BOARD)) { + conn.transaction(() -> u.call(job, board)); + } + } + + protected JobState getJobState(int job) { + try (var q = conn.query(GET_JOB)) { + return conn.transaction(() -> q.call1(job).orElseThrow() + .getEnum("job_state", JobState.class)); + } + } + + protected int getJobRequestCount() { + try (var q = conn.query(TEST_COUNT_REQUESTS)) { + return conn.transaction( + () -> q.call1(QUEUED).orElseThrow().getInt("cnt")); + } + } + + protected int getPendingPowerChanges() { + try (var q = conn.query(TEST_COUNT_POWER_CHANGES)) { + return conn + .transaction(() -> q.call1().orElseThrow().getInt("cnt")); + } + } + + // Wrappers for temporarily putting the DB into a state with a job/alloc + + protected int makeJob() { + return db.execute(c -> makeJob(c, null, QUEUED, null, + ofEpochMilli(0), null, null, ofSeconds(0), now())); + } + + protected void withJob(IntConsumer act) { + int jobId = makeJob(); + try { + act.accept(jobId); + } finally { + nukeJob(jobId); + } + } + + protected void nukeJob(int jobId) { + db.executeVoid(c -> { + try (var u = c.update("DELETE FROM jobs WHERE job_id = ?")) { + u.call(jobId); + } + }); + } + + protected void withAllocation(int jobId, Runnable act) { + db.executeVoid(c -> { + allocateBoardToJob(c, BOARD, jobId); + setAllocRoot(c, jobId, BOARD); + }); + try { + act.run(); + } finally { + db.executeVoid(c -> { + allocateBoardToJob(c, BOARD, null); + setAllocRoot(c, jobId, null); + }); + } + } + + protected void withStandardAllocatedJob(ObjIntConsumer act) { + // Composite op, for brevity + withJob(jobId -> inContext(c -> withAllocation(jobId, + () -> act.accept(c.setAuth(USER_NAME), jobId)))); + } + + private static final int DELAY_MS = 1000; + + /** Sleep for one second. */ + protected static void snooze1s() { + try { + Thread.sleep(DELAY_MS); + } catch (InterruptedException e) { + assumeTrue(false, "sleep() was interrupted"); + } + } + + /** Capability provided by {@link #inContext(InC)} to what it guards. */ + public interface C { + /** + * Install an authentication token. + * + * @param auth + * The authentication token to install. {@code null} to + * remove. + */ + void setAuth(Authentication auth); + + /** + * Install the named user as the current user and provide a permit that + * allows that user to touch resources. + * + * @param name + * The user name. + * @return The newly-minted permit. + */ + default Permit setAuth(String name) { + @SuppressWarnings("serial") + var a = new Authentication() { + @Override + public String getName() { + return name; + } + + @Override + public Collection getAuthorities() { + return List.of(); + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public Object getPrincipal() { + return null; + } + + @Override + public boolean isAuthenticated() { + return true; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) { + } + }; + setAuth(a); + return new Permit(SecurityContextHolder.getContext()); + } + } + + /** + * An action wrapped by {@link #inContext(InC)}. + */ + public interface InC { + /** + * The wrapped action. + * + * @param c + * The capability to set the current user. + */ + void act(C c); + } + + /** + * Run code with the capability to set the current user. Will clean up + * afterwards. + * + * @param inc + * The code to run. + */ + public static void inContext(InC inc) { + var context = SecurityContextHolder.getContext(); + try { + inc.act(context::setAuthentication); + } finally { + context.setAuthentication(null); + } + } +} 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 610635d2ad..5be85258c1 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 @@ -1,291 +1,291 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.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 java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.CRC32; - -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; -import uk.ac.manchester.spinnaker.messages.model.BMPConnectionData; -import uk.ac.manchester.spinnaker.messages.model.Blacklist; -import uk.ac.manchester.spinnaker.messages.model.FPGA; -import uk.ac.manchester.spinnaker.messages.model.PowerCommand; -import uk.ac.manchester.spinnaker.messages.model.VersionInfo; -import uk.ac.manchester.spinnaker.transceiver.UnimplementedBMPTransceiver; -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * BMP transceiver mock just for test purposes. - */ -public final class MockTransceiver extends UnimplementedBMPTransceiver { - private static final Logger log = getLogger(MockTransceiver.class); - - /** - * Install this mock transceiver as the thing to be manufactured by the - * given transceiver factory. - * - * @param txrxFactory - * The transceiver factory to install into. - */ - @SuppressWarnings("deprecation") - public static void installIntoFactory(TransceiverFactory txrxFactory) { - txrxFactory.getTestAPI().setFactory(MockTransceiver::new); - } - - private static MockTransceiver current; - - public static MockTransceiver getCurrentMock() { - return current; - } - - /** Not a real serial number at all! Just for testing purposes. */ - private static final String SERIAL_NUMBER = "gorp"; - - private static final int VERSION_INFO_SIZE = 32; - - /** Dummy version code. */ - static final short VERSION = 0x202; - - /** Initial dummy blacklist data. */ - static final String BLACKLIST = "chip 5 5 core 5"; - - private static String blacklistData = BLACKLIST; - - private static VersionInfo version = - new VersionInfo(syntheticVersionData(VERSION), true); - - private Map status; - - @GuardedBy("itself") - private final ValueHolder setBlacklist; - - private MockTransceiver(String machineName, BMPConnectionData data, - ValueHolder setBlacklist) { - log.info("constructed dummy transceiver for {} ({} : {})", machineName, - data.ipAddress, data.boards); - status = new HashMap<>(); - this.setBlacklist = setBlacklist; - current = this; - } - - public static void setVersion(short versionCode) { - version = new VersionInfo(syntheticVersionData(versionCode), true); - } - - public static void setBlacklist(String blacklist) { - blacklistData = blacklist; - } - - /** - * @return The bytes of a response, correct in the places which Spalloc - * checks, and arbitrary (zero) elsewhere. - */ - private static ByteBuffer syntheticVersionData(short versionCode) { - byte zero = 0; - var b = allocate(VERSION_INFO_SIZE).order(LITTLE_ENDIAN); - b.put(zero); - b.put(zero); - b.put(zero); - b.put(zero); - b.putShort((short) 0); - b.putShort(versionCode); - b.putInt(0); - b.put("abc/def".getBytes(UTF_8)); - return b.flip(); - } - - public Map getStatus() { - return unmodifiableMap(status); - } - - @Override - 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); - } - } - - /** - * A place where you can set a queue of wonky results from the read of the - * FPGA registers. - */ - @SuppressWarnings("checkstyle:visibilitymodifier") - public static ArrayDeque fpgaResults = new ArrayDeque<>(); - - @Override - public int readFPGARegister(FPGA fpga, MemoryLocation register, - BMPCoords bmp, BMPBoard board) { - log.info("readFPGARegister({},{},{},{})", fpga, register, bmp, board); - var r = fpgaResults.pollFirst(); - if (r != null) { - return r.value; - } - return fpga.value; - } - - @Override - public void writeFPGARegister(FPGA fpga, MemoryLocation register, int value, - BMPCoords bmp, BMPBoard board) { - log.info("writeFPGARegister({},{},{},{},{})", fpga, register, value, - bmp, board); - } - - @Override - public VersionInfo readBMPVersion(BMPCoords bmp, BMPBoard board) { - log.info("readBMPVersion({},{})", bmp, board); - return version; - } - - @Override - public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) { - log.info("readBoardSerialNumber({},{})", bmp, board); - return SERIAL_NUMBER; - } - - private static final int MEM_SIZE = 8 * 1024 * 1024; - - private static ByteBuffer allocateMemory() { - var buf = allocate(MEM_SIZE).order(LITTLE_ENDIAN); - buf.position(0).limit(MEM_SIZE); - return buf; - } - - private ByteBuffer memory = allocateMemory(); - - private ByteBuffer flash = allocateMemory(); - - @Override - public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, - length); - // Pad to length - var b = slice(flash, baseAddress.address, length); - if (baseAddress.address == SERIAL_FLASH_BLACKLIST_OFFSET) { - b.put(new Blacklist(blacklistData).getRawData()); - b.position(0); - } - return b; - } - - @Override - public ByteBuffer readBMPMemory(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readBMPMemory({},{},{},{})", bmp, board, baseAddress, length); - return slice(memory, baseAddress.address, length); - } - - @Override - public MemoryLocation getSerialFlashBuffer(BMPCoords bmp, BMPBoard board) { - log.info("getSerialFlashBuffer({},{})", bmp, board); - return MemoryLocation.NULL; - } - - @Override - 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()) - .put(data.duplicate()); - } - - @Override - public void writeFlash(@Valid BMPCoords bmp, @Valid BMPBoard board, - @NotNull MemoryLocation baseAddress, @NotNull ByteBuffer data, - boolean update) { - log.info("writeFlash({},{},{},{})", bmp, board, baseAddress, - data.remaining()); - var blData = data.duplicate().position(BMP_FLASH_BLACKLIST_OFFSET); - synchronized (setBlacklist) { - setBlacklist.setValue(new Blacklist(blData)); - } - } - - private static final int BMP_FLASH_BLACKLIST_OFFSET = 0xe00; - - private static final int SERIAL_FLASH_BLACKLIST_OFFSET = 0x100; - - @Override - 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); - b.position(SERIAL_FLASH_BLACKLIST_OFFSET); - var bl = new Blacklist(b); - synchronized (setBlacklist) { - if (!bl.equals(setBlacklist.getValue())) { - throw new IllegalStateException("blacklist in serial flash (" - + bl + ") is different to blacklist in BMP flash (" - + setBlacklist.getValue() + ")"); - } - } - } - - @Override - public void writeSerialFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int size, InputStream stream) - throws IOException { - log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress, - size); - slice(flash, baseAddress.address, size).put(readFully(stream, size)); - } - - @Override - public void writeBMPFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress) { - log.info("writeBMPFlash({},{},{})", bmp, board, baseAddress); - } - - private static final long CRC_MASK = 0xffffffffL; - - @Override - public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress, - length); - var crc = new CRC32(); - crc.update(slice(flash, baseAddress.address, length)); - return (int) (crc.getValue() & CRC_MASK); - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.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 java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.CRC32; + +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; +import uk.ac.manchester.spinnaker.messages.model.BMPConnectionData; +import uk.ac.manchester.spinnaker.messages.model.Blacklist; +import uk.ac.manchester.spinnaker.messages.model.FPGA; +import uk.ac.manchester.spinnaker.messages.model.PowerCommand; +import uk.ac.manchester.spinnaker.messages.model.VersionInfo; +import uk.ac.manchester.spinnaker.transceiver.UnimplementedBMPTransceiver; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * BMP transceiver mock just for test purposes. + */ +public final class MockTransceiver extends UnimplementedBMPTransceiver { + private static final Logger log = getLogger(MockTransceiver.class); + + /** + * Install this mock transceiver as the thing to be manufactured by the + * given transceiver factory. + * + * @param txrxFactory + * The transceiver factory to install into. + */ + @SuppressWarnings("deprecation") + public static void installIntoFactory(TransceiverFactory txrxFactory) { + txrxFactory.getTestAPI().setFactory(MockTransceiver::new); + } + + private static MockTransceiver current; + + public static MockTransceiver getCurrentMock() { + return current; + } + + /** Not a real serial number at all! Just for testing purposes. */ + private static final String SERIAL_NUMBER = "gorp"; + + private static final int VERSION_INFO_SIZE = 32; + + /** Dummy version code. */ + static final short VERSION = 0x202; + + /** Initial dummy blacklist data. */ + static final String BLACKLIST = "chip 5 5 core 5"; + + private static String blacklistData = BLACKLIST; + + private static VersionInfo version = + new VersionInfo(syntheticVersionData(VERSION), true); + + private Map status; + + @GuardedBy("itself") + private final ValueHolder setBlacklist; + + private MockTransceiver(String machineName, BMPConnectionData data, + ValueHolder setBlacklist) { + log.info("constructed dummy transceiver for {} ({} : {})", machineName, + data.ipAddress, data.boards); + status = new HashMap<>(); + this.setBlacklist = setBlacklist; + current = this; + } + + public static void setVersion(short versionCode) { + version = new VersionInfo(syntheticVersionData(versionCode), true); + } + + public static void setBlacklist(String blacklist) { + blacklistData = blacklist; + } + + /** + * @return The bytes of a response, correct in the places which Spalloc + * checks, and arbitrary (zero) elsewhere. + */ + private static ByteBuffer syntheticVersionData(short versionCode) { + byte zero = 0; + var b = allocate(VERSION_INFO_SIZE).order(LITTLE_ENDIAN); + b.put(zero); + b.put(zero); + b.put(zero); + b.put(zero); + b.putShort((short) 0); + b.putShort(versionCode); + b.putInt(0); + b.put("abc/def".getBytes(UTF_8)); + return b.flip(); + } + + public Map getStatus() { + return unmodifiableMap(status); + } + + @Override + 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); + } + } + + /** + * A place where you can set a queue of wonky results from the read of the + * FPGA registers. + */ + @SuppressWarnings("checkstyle:visibilitymodifier") + public static ArrayDeque fpgaResults = new ArrayDeque<>(); + + @Override + public int readFPGARegister(FPGA fpga, MemoryLocation register, + BMPCoords bmp, BMPBoard board) { + log.info("readFPGARegister({},{},{},{})", fpga, register, bmp, board); + var r = fpgaResults.pollFirst(); + if (r != null) { + return r.value; + } + return fpga.value; + } + + @Override + public void writeFPGARegister(FPGA fpga, MemoryLocation register, int value, + BMPCoords bmp, BMPBoard board) { + log.info("writeFPGARegister({},{},{},{},{})", fpga, register, value, + bmp, board); + } + + @Override + public VersionInfo readBMPVersion(BMPCoords bmp, BMPBoard board) { + log.info("readBMPVersion({},{})", bmp, board); + return version; + } + + @Override + public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) { + log.info("readBoardSerialNumber({},{})", bmp, board); + return SERIAL_NUMBER; + } + + private static final int MEM_SIZE = 8 * 1024 * 1024; + + private static ByteBuffer allocateMemory() { + var buf = allocate(MEM_SIZE).order(LITTLE_ENDIAN); + buf.position(0).limit(MEM_SIZE); + return buf; + } + + private ByteBuffer memory = allocateMemory(); + + private ByteBuffer flash = allocateMemory(); + + @Override + public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, + length); + // Pad to length + var b = slice(flash, baseAddress.address, length); + if (baseAddress.address == SERIAL_FLASH_BLACKLIST_OFFSET) { + b.put(new Blacklist(blacklistData).getRawData()); + b.position(0); + } + return b; + } + + @Override + public ByteBuffer readBMPMemory(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readBMPMemory({},{},{},{})", bmp, board, baseAddress, length); + return slice(memory, baseAddress.address, length); + } + + @Override + public MemoryLocation getSerialFlashBuffer(BMPCoords bmp, BMPBoard board) { + log.info("getSerialFlashBuffer({},{})", bmp, board); + return MemoryLocation.NULL; + } + + @Override + 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()) + .put(data.duplicate()); + } + + @Override + public void writeFlash(@Valid BMPCoords bmp, @Valid BMPBoard board, + @NotNull MemoryLocation baseAddress, @NotNull ByteBuffer data, + boolean update) { + log.info("writeFlash({},{},{},{})", bmp, board, baseAddress, + data.remaining()); + var blData = data.duplicate().position(BMP_FLASH_BLACKLIST_OFFSET); + synchronized (setBlacklist) { + setBlacklist.setValue(new Blacklist(blData)); + } + } + + private static final int BMP_FLASH_BLACKLIST_OFFSET = 0xe00; + + private static final int SERIAL_FLASH_BLACKLIST_OFFSET = 0x100; + + @Override + 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); + b.position(SERIAL_FLASH_BLACKLIST_OFFSET); + var bl = new Blacklist(b); + synchronized (setBlacklist) { + if (!bl.equals(setBlacklist.getValue())) { + throw new IllegalStateException("blacklist in serial flash (" + + bl + ") is different to blacklist in BMP flash (" + + setBlacklist.getValue() + ")"); + } + } + } + + @Override + public void writeSerialFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int size, InputStream stream) + throws IOException { + log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress, + size); + slice(flash, baseAddress.address, size).put(readFully(stream, size)); + } + + @Override + public void writeBMPFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress) { + log.info("writeBMPFlash({},{},{})", bmp, board, baseAddress); + } + + private static final long CRC_MASK = 0xffffffffL; + + @Override + public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress, + length); + var crc = new CRC32(); + crc.update(slice(flash, baseAddress.address, length)); + return (int) (crc.getValue() & CRC_MASK); + } +} diff --git a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java index e4ac719e08..12d88413c3 100644 --- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java +++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.db; - -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * Support class for doing testing against an in-memory database. There will be - * a connection per test (i.e., the DB will be implicitly deleted at the end of - * each test), with that connection made available in the {@link #c} - * field. That field must not be modified by subclasses. - *

- * Subclasses should be annotated with {@link SpringBootTest}. - */ -@UsedInJavadocOnly(SpringBootTest.class) -public abstract class MemDBTestBase extends SQLQueries { - private DatabaseEngine memdb; - - /** - * The DB connection. Only valid in a test. Must not be modified by - * subclasses. - */ - @SuppressWarnings("checkstyle:visibilitymodifier") - protected Connection c; - - @BeforeAll - void getMemoryDatabase(@Autowired DatabaseEngine mainDBEngine) { - assumeTrue(mainDBEngine != null, "spring-configured DB engine absent"); - memdb = mainDBEngine.getInMemoryDB(); - } - - @BeforeEach - @SuppressWarnings("MustBeClosed") - void getConnection() { - c = memdb.getConnection(); - assumeTrue(c != null, "connection not generated"); - } - - @AfterEach - void closeConnection() { - c.close(); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.db; + +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * Support class for doing testing against an in-memory database. There will be + * a connection per test (i.e., the DB will be implicitly deleted at the end of + * each test), with that connection made available in the {@link #c} + * field. That field must not be modified by subclasses. + *

+ * Subclasses should be annotated with {@link SpringBootTest}. + */ +@UsedInJavadocOnly(SpringBootTest.class) +public abstract class MemDBTestBase extends SQLQueries { + private DatabaseEngine memdb; + + /** + * The DB connection. Only valid in a test. Must not be modified by + * subclasses. + */ + @SuppressWarnings("checkstyle:visibilitymodifier") + protected Connection c; + + @BeforeAll + void getMemoryDatabase(@Autowired DatabaseEngine mainDBEngine) { + assumeTrue(mainDBEngine != null, "spring-configured DB engine absent"); + memdb = mainDBEngine.getInMemoryDB(); + } + + @BeforeEach + @SuppressWarnings("MustBeClosed") + void getConnection() { + c = memdb.getConnection(); + assumeTrue(c != null, "connection not generated"); + } + + @AfterEach + void closeConnection() { + c.close(); + } +} diff --git a/SpiNNaker-allocserv/src/test/resources/three-board-example.json b/SpiNNaker-allocserv/src/test/resources/three-board-example.json index d051efbc05..22d901c45b 100644 --- a/SpiNNaker-allocserv/src/test/resources/three-board-example.json +++ b/SpiNNaker-allocserv/src/test/resources/three-board-example.json @@ -1 +1 @@ -{"machines":[{"name":"SpiNNaker3board","tags":["machine-room","default"],"width":1,"height":1,"dead-boards":[],"dead-links":{},"board-locations":{"[x:0,y:0,z:0]":{"c":0,"f":0,"b":0},"[x:0,y:0,z:1]":{"c":0,"f":0,"b":2},"[x:0,y:0,z:2]":{"c":0,"f":0,"b":1}},"bmp-ips":{"[c:0,f:0]":"10.11.193.0"},"spinnaker-ips":{"[x:0,y:0,z:0]":"10.11.193.1","[x:0,y:0,z:1]":"10.11.193.17","[x:0,y:0,z:2]":"10.11.193.9"}}],"port":22244,"ip":"127.0.0.1","timeout-check-interval":5.0,"max-retired-jobs":1200,"seconds-before-free":30} \ No newline at end of file +{"machines":[{"name":"SpiNNaker3board","tags":["machine-room","default"],"width":1,"height":1,"dead-boards":[],"dead-links":{},"board-locations":{"[x:0,y:0,z:0]":{"c":0,"f":0,"b":0},"[x:0,y:0,z:1]":{"c":0,"f":0,"b":2},"[x:0,y:0,z:2]":{"c":0,"f":0,"b":1}},"bmp-ips":{"[c:0,f:0]":"10.11.193.0"},"spinnaker-ips":{"[x:0,y:0,z:0]":"10.11.193.1","[x:0,y:0,z:1]":"10.11.193.17","[x:0,y:0,z:2]":"10.11.193.9"}}],"port":22244,"ip":"127.0.0.1","timeout-check-interval":5.0,"max-retired-jobs":1200,"seconds-before-free":30} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java index 9a43ea2840..b24f518c2e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.net.SocketTimeoutException; -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.BlockingQueue; - -/** Shared helper because we can't use a superclass. */ -abstract class ClientUtils { - private ClientUtils() { - } - - /** - * Receive a message from a queue or time out. - * - * @param received - * Where to receive from. - * @param timeout - * Timeout, in milliseconds. - * @return The message. - * @throws InterruptedException - * If communications are interrupted. - * @throws SocketTimeoutException - * If a timeout happens. - */ - static ByteBuffer receiveHelper(BlockingQueue received, - long timeout) throws SocketTimeoutException, InterruptedException { - var msg = received.poll(timeout, MILLISECONDS); - if (isNull(msg)) { - throw new SocketTimeoutException(); - } - return msg; - } - - /** - * Add a {@code /} to the end of the path part of a URI. - * - * @param uri - * The URI to amend. Assumed to be HTTP or HTTPS. - * @return The amended URI. - */ - static URI asDir(URI uri) { - var path = uri.getPath(); - if (!path.endsWith("/")) { - path += "/"; - uri = uri.resolve(path); - } - return uri; - } - - /** - * Make a read-only shallow copy of a list. - * - * @param - * The type of elements in the list. These are - * recommended to be immutable, but this is not - * enforced. - * @param list - * The list to make a read-only copy of. The elements in the list - * are not themselves copied. - * @return The read-only copy. - */ - static List readOnlyCopy(List list) { - return Objects.isNull(list) ? List.of() : List.copyOf(list); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.net.SocketTimeoutException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.BlockingQueue; + +/** Shared helper because we can't use a superclass. */ +abstract class ClientUtils { + private ClientUtils() { + } + + /** + * Receive a message from a queue or time out. + * + * @param received + * Where to receive from. + * @param timeout + * Timeout, in milliseconds. + * @return The message. + * @throws InterruptedException + * If communications are interrupted. + * @throws SocketTimeoutException + * If a timeout happens. + */ + static ByteBuffer receiveHelper(BlockingQueue received, + long timeout) throws SocketTimeoutException, InterruptedException { + var msg = received.poll(timeout, MILLISECONDS); + if (isNull(msg)) { + throw new SocketTimeoutException(); + } + return msg; + } + + /** + * Add a {@code /} to the end of the path part of a URI. + * + * @param uri + * The URI to amend. Assumed to be HTTP or HTTPS. + * @return The amended URI. + */ + static URI asDir(URI uri) { + var path = uri.getPath(); + if (!path.endsWith("/")) { + path += "/"; + uri = uri.resolve(path); + } + return uri; + } + + /** + * Make a read-only shallow copy of a list. + * + * @param + * The type of elements in the list. These are + * recommended to be immutable, but this is not + * enforced. + * @param list + * The list to make a read-only copy of. The elements in the list + * are not themselves copied. + * @return The read-only copy. + */ + static List readOnlyCopy(List list) { + return Objects.isNull(list) ? List.of() : List.copyOf(list); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java index 982859134c..f64da3be11 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java @@ -1,104 +1,104 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; -import static java.util.Objects.requireNonNull; -import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO; - -import java.io.EOFException; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.BootConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; - -/** A boot connection that routes messages across the proxy. */ -final class ProxiedBootConnection extends BootConnection { - /** The port of the connection. */ - private static final int BOOT_PORT = 54321; - - private final ProxyProtocolClient.ConnectedChannel channel; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - /** - * @param ws - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If interrupted while things were setting up. - */ - ProxiedBootConnection(ProxyProtocolClient ws) - throws IOException, InterruptedException { - this.ws = requireNonNull(ws); - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openChannel(ZERO_ZERO, BOOT_PORT, receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - protected void doSend(ByteBuffer buffer) throws IOException { - channel.send(buffer); - } - - @Override - @DoNotCall - protected void doSendTo(ByteBuffer data, InetAddress address, int port) { - throw new UnsupportedOperationException( - "sendTo() not supported by this connection type"); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; +import static java.util.Objects.requireNonNull; +import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO; + +import java.io.EOFException; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.BootConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; + +/** A boot connection that routes messages across the proxy. */ +final class ProxiedBootConnection extends BootConnection { + /** The port of the connection. */ + private static final int BOOT_PORT = 54321; + + private final ProxyProtocolClient.ConnectedChannel channel; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + /** + * @param ws + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If interrupted while things were setting up. + */ + ProxiedBootConnection(ProxyProtocolClient ws) + throws IOException, InterruptedException { + this.ws = requireNonNull(ws); + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openChannel(ZERO_ZERO, BOOT_PORT, receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + protected void doSend(ByteBuffer buffer) throws IOException { + channel.send(buffer); + } + + @Override + @DoNotCall + protected void doSendTo(ByteBuffer data, InetAddress address, int port) { + throw new UnsupportedOperationException( + "sendTo() not supported by this connection type"); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java index 5a9a8a66e7..1e4d00b773 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java @@ -1,97 +1,97 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; - -import java.io.EOFException; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.EIEIOConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -final class ProxiedEIEIOListenerConnection extends EIEIOConnection { - private final Map hostToChip; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - private ProxyProtocolClient.UnconnectedChannel channel; - - ProxiedEIEIOListenerConnection(Map hostToChip, - ProxyProtocolClient proxy) - throws InterruptedException { - this.hostToChip = hostToChip; - this.ws = proxy; - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openUnconnectedChannel(receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - @DoNotCall - protected void doSend(ByteBuffer buffer) { - throw new UnsupportedOperationException(); - } - - @Override - protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) - throws IOException { - channel.send(hostToChip.get(addr), port, buffer); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; + +import java.io.EOFException; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.EIEIOConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +final class ProxiedEIEIOListenerConnection extends EIEIOConnection { + private final Map hostToChip; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + private ProxyProtocolClient.UnconnectedChannel channel; + + ProxiedEIEIOListenerConnection(Map hostToChip, + ProxyProtocolClient proxy) + throws InterruptedException { + this.hostToChip = hostToChip; + this.ws = proxy; + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openUnconnectedChannel(receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + @DoNotCall + protected void doSend(ByteBuffer buffer) { + throw new UnsupportedOperationException(); + } + + @Override + protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) + throws IOException { + channel.send(hostToChip.get(addr), port, buffer); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java index 49be9cc27c..86a7aa0bb7 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; - -import java.io.EOFException; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** An SCP connection that routes messages across the proxy. */ -final class ProxiedSCPConnection extends SCPConnection { - /** The port of the connection. */ - private static final int SCP_SCAMP_PORT = 17893; - - private final ProxyProtocolClient.ConnectedChannel channel; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - /** - * @param chip - * Which ethernet chip in the job are we talking to? - * @param ws - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If interrupted while things were setting up. - */ - ProxiedSCPConnection(ChipLocation chip, ProxyProtocolClient ws) - throws IOException, InterruptedException { - super(chip); - this.ws = ws; - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openChannel(chip, SCP_SCAMP_PORT, receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - protected void doSend(ByteBuffer buffer) throws IOException { - channel.send(buffer); - } - - @Override - @DoNotCall - protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) - throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } - - /** - * Close this connection eventually. Actually processes it immediately - * because the other end of the proxy makes it eventual. - */ - @Override - public void closeEventually() { - closeAndLogNoExcept(); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; + +import java.io.EOFException; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** An SCP connection that routes messages across the proxy. */ +final class ProxiedSCPConnection extends SCPConnection { + /** The port of the connection. */ + private static final int SCP_SCAMP_PORT = 17893; + + private final ProxyProtocolClient.ConnectedChannel channel; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + /** + * @param chip + * Which ethernet chip in the job are we talking to? + * @param ws + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If interrupted while things were setting up. + */ + ProxiedSCPConnection(ChipLocation chip, ProxyProtocolClient ws) + throws IOException, InterruptedException { + super(chip); + this.ws = ws; + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openChannel(chip, SCP_SCAMP_PORT, receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + protected void doSend(ByteBuffer buffer) throws IOException { + channel.send(buffer); + } + + @Override + @DoNotCall + protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) + throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } + + /** + * Close this connection eventually. Actually processes it immediately + * because the other end of the proxy makes it eventual. + */ + @Override + public void closeEventually() { + closeAndLogNoExcept(); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java index 8c751f61ca..1d06160eea 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static uk.ac.manchester.spinnaker.machine.MachineVersion.TRIAD_NO_WRAPAROUND; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.Collection; -import java.util.Map; - -import uk.ac.manchester.spinnaker.connections.EIEIOConnection; -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.connections.model.Connection; -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.transceiver.SpinnmanException; -import uk.ac.manchester.spinnaker.transceiver.Transceiver; - -/** A transceiver that routes messages across the proxy. */ -final class ProxiedTransceiver extends Transceiver { - private final ProxyProtocolClient websocket; - - private final Map hostToChip; - - /** - * @param connections - * The proxied connections we will use. - * @param hostToChip - * The mapping from addresses to chip locations, to enable - * manufacturing of proxied {@link EIEIOConnection}s. - * @param websocket - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If communications are interrupted. - * @throws SpinnmanExcception - * If SpiNNaker rejects a message. - */ - ProxiedTransceiver(Collection connections, - Map hostToChip, - ProxyProtocolClient websocket) - throws IOException, SpinnmanException, InterruptedException { - // Assume unwrapped - super(TRIAD_NO_WRAPAROUND, connections, null, null, null, null, - null); - this.hostToChip = hostToChip; - this.websocket = websocket; - } - - /** {@inheritDoc} */ - @Override - public void close() throws IOException { - super.close(); - websocket.close(); - } - - @Override - public SCPConnection createScpConnection(ChipLocation chip, - InetAddress addr) throws IOException { - try { - return new ProxiedSCPConnection(chip, websocket); - } catch (InterruptedException e) { - throw new IOException("failed to proxy connection", e); - } - } - - @Override - protected EIEIOConnection newEieioConnection(InetAddress localHost, - Integer localPort) throws IOException { - try { - return new ProxiedEIEIOListenerConnection(hostToChip, websocket); - } catch (InterruptedException e) { - throw new IOException("failed to proxy connection", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static uk.ac.manchester.spinnaker.machine.MachineVersion.TRIAD_NO_WRAPAROUND; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.util.Collection; +import java.util.Map; + +import uk.ac.manchester.spinnaker.connections.EIEIOConnection; +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.connections.model.Connection; +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.transceiver.SpinnmanException; +import uk.ac.manchester.spinnaker.transceiver.Transceiver; + +/** A transceiver that routes messages across the proxy. */ +final class ProxiedTransceiver extends Transceiver { + private final ProxyProtocolClient websocket; + + private final Map hostToChip; + + /** + * @param connections + * The proxied connections we will use. + * @param hostToChip + * The mapping from addresses to chip locations, to enable + * manufacturing of proxied {@link EIEIOConnection}s. + * @param websocket + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If communications are interrupted. + * @throws SpinnmanExcception + * If SpiNNaker rejects a message. + */ + ProxiedTransceiver(Collection connections, + Map hostToChip, + ProxyProtocolClient websocket) + throws IOException, SpinnmanException, InterruptedException { + // Assume unwrapped + super(TRIAD_NO_WRAPAROUND, connections, null, null, null, null, + null); + this.hostToChip = hostToChip; + this.websocket = websocket; + } + + /** {@inheritDoc} */ + @Override + public void close() throws IOException { + super.close(); + websocket.close(); + } + + @Override + public SCPConnection createScpConnection(ChipLocation chip, + InetAddress addr) throws IOException { + try { + return new ProxiedSCPConnection(chip, websocket); + } catch (InterruptedException e) { + throw new IOException("failed to proxy connection", e); + } + } + + @Override + protected EIEIOConnection newEieioConnection(InetAddress localHost, + Integer localPort) throws IOException { + try { + return new ProxiedEIEIOListenerConnection(hostToChip, websocket); + } catch (InterruptedException e) { + throw new IOException("failed to proxy connection", e); + } + } +} 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 db4da86fc5..67ee75b81a 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 @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -import java.nio.ByteBuffer; - -/** Message IDs in the proxy protocol. */ -enum ProxyProtocol { - /** Open a connected channel, or its response. Two-way. */ - OPEN(20), - /** Close a channel, or its response. Two-way. */ - CLOSE(12), - /** Send a message on a connected channel, or receive a message. One-way. */ - MSG(1600), - /** Open an unconnected channel, or its response. Two-way. */ - OPEN_U(8), - /** Send a message on an unconnected channel. Never received. One-way. */ - MSG_TO(1600); - - private final int size; - - ProxyProtocol(int size) { - this.size = size; - } - - /** - * Create a buffer big enough to hold a message and fill the first word with - * the protocol ID. - * - * @return A little endian buffer of sufficient size. Position will be after - * first word. - */ - ByteBuffer allocate() { - var b = ByteBuffer.allocate(size).order(LITTLE_ENDIAN); - b.putInt(ordinal()); - return b; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.nio.ByteOrder.LITTLE_ENDIAN; + +import java.nio.ByteBuffer; + +/** Message IDs in the proxy protocol. */ +enum ProxyProtocol { + /** Open a connected channel, or its response. Two-way. */ + OPEN(20), + /** Close a channel, or its response. Two-way. */ + CLOSE(12), + /** Send a message on a connected channel, or receive a message. One-way. */ + MSG(1600), + /** Open an unconnected channel, or its response. Two-way. */ + OPEN_U(8), + /** Send a message on an unconnected channel. Never received. One-way. */ + MSG_TO(1600); + + private final int size; + + ProxyProtocol(int size) { + this.size = size; + } + + /** + * Create a buffer big enough to hold a message and fill the first word with + * the protocol ID. + * + * @return A little endian buffer of sufficient size. Position will be after + * first word. + */ + ByteBuffer allocate() { + var b = ByteBuffer.allocate(size).order(LITTLE_ENDIAN); + b.putInt(ordinal()); + return b; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java index d2ebbd499b..46c7c96d4f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import java.io.Closeable; -import java.io.IOException; -import java.net.Inet4Address; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** - * Our interface that specifies what top-level operations can be done by the UDP - * socket proxying system. Used to hide the details of the websocket from code - * that doesn't need to care and shouldn't care. - */ -interface ProxyProtocolClient extends AutoCloseable { - /** - * Open a connected channel to a SpiNNaker board in the current job. - * - * @param chip - * The coordinates of the ethernet chip of the board to connect - * to. - * @param port - * The UDP port to connect to. - * @param receiveQueue - * Where to enqueue received messages. - * @return The connected channel. - * @throws InterruptedException - * If interrupted while waiting for a reply. - */ - ConnectedChannel openChannel(ChipLocation chip, int port, - BlockingQueue receiveQueue) throws InterruptedException; - - /** - * Open an unconnected channel to any SpiNNaker board in the current job. - * - * @param receiveQueue - * Where to enqueue received messages. - * @return The unconnected channel. - * @throws InterruptedException - * If interrupted while waiting for a reply. - */ - UnconnectedChannel openUnconnectedChannel( - BlockingQueue receiveQueue) throws InterruptedException; - - /** - * Is the underlying websocket in the state OPEN. - * - * @return state equals ReadyState.OPEN - */ - boolean isOpen(); - - /** - * {@inheritDoc} - *

- * Note that this may process the close asynchronously. - */ - @Override - void close(); - - interface ConnectedChannel extends Closeable { - /** - * Send a message to the board that the channel is connected to. - * - * @param msg - * The payload of the message to send. Might be a serialized - * SDP message, for example. - * @throws IOException - * If the message cannot be sent. - */ - void send(ByteBuffer msg) throws IOException; - } - - interface UnconnectedChannel extends Closeable { - /** - * @return The "local" address for this channel. - */ - Inet4Address getAddress(); - - /** - * @return The "local" port for this channel. - */ - int getPort(); - - /** - * Send a message to a board in the allocation of the current job. - * - * @param chip - * Which ethernet chip to send to. - * @param port - * Which UDP port to send to. - * @param msg - * The payload of the message to send. Might be a serialized - * SDP message, for example. - * @throws IOException - * If the message cannot be sent. - */ - void send(ChipLocation chip, int port, ByteBuffer msg) - throws IOException; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import java.io.Closeable; +import java.io.IOException; +import java.net.Inet4Address; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** + * Our interface that specifies what top-level operations can be done by the UDP + * socket proxying system. Used to hide the details of the websocket from code + * that doesn't need to care and shouldn't care. + */ +interface ProxyProtocolClient extends AutoCloseable { + /** + * Open a connected channel to a SpiNNaker board in the current job. + * + * @param chip + * The coordinates of the ethernet chip of the board to connect + * to. + * @param port + * The UDP port to connect to. + * @param receiveQueue + * Where to enqueue received messages. + * @return The connected channel. + * @throws InterruptedException + * If interrupted while waiting for a reply. + */ + ConnectedChannel openChannel(ChipLocation chip, int port, + BlockingQueue receiveQueue) throws InterruptedException; + + /** + * Open an unconnected channel to any SpiNNaker board in the current job. + * + * @param receiveQueue + * Where to enqueue received messages. + * @return The unconnected channel. + * @throws InterruptedException + * If interrupted while waiting for a reply. + */ + UnconnectedChannel openUnconnectedChannel( + BlockingQueue receiveQueue) throws InterruptedException; + + /** + * Is the underlying websocket in the state OPEN. + * + * @return state equals ReadyState.OPEN + */ + boolean isOpen(); + + /** + * {@inheritDoc} + *

+ * Note that this may process the close asynchronously. + */ + @Override + void close(); + + interface ConnectedChannel extends Closeable { + /** + * Send a message to the board that the channel is connected to. + * + * @param msg + * The payload of the message to send. Might be a serialized + * SDP message, for example. + * @throws IOException + * If the message cannot be sent. + */ + void send(ByteBuffer msg) throws IOException; + } + + interface UnconnectedChannel extends Closeable { + /** + * @return The "local" address for this channel. + */ + Inet4Address getAddress(); + + /** + * @return The "local" port for this channel. + */ + int getPort(); + + /** + * Send a message to a board in the allocation of the current job. + * + * @param chip + * Which ethernet chip to send to. + * @param port + * Which UDP port to send to. + * @param msg + * The payload of the message to send. Might be a serialized + * SDP message, for example. + * @throws IOException + * If the message cannot be sent. + */ + void send(ChipLocation chip, int port, ByteBuffer msg) + throws IOException; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java index 55073e3308..a2b57e4867 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.client; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URLConnection; -import java.util.concurrent.Callable; - -/** - * Operations on the low level session that are intended to be used by the - * client. - */ -interface Session { - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, String url2, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, URI url2, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @return the connection, which should not be used to change the service - * state. - * @throws IOException - * If things go wrong - */ - default HttpURLConnection connection(URI url, URI url2) throws IOException { - return connection(url, url2, false); - } - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @return the connection, which should not be used to change the service - * state. - * @throws IOException - * If things go wrong - */ - default HttpURLConnection connection(URI url) throws IOException { - return connection(url, false); - } - - /** - * Check for and handle any session cookie changes. - *

- * Assumes that the session key is in the {@code JSESSIONID} cookie. - * - * @param conn - * Connection that's had a transaction processed. - * @return Whether the session cookie was set. Normally uninteresting. - */ - boolean trackCookie(HttpURLConnection conn); - - /** - * An action used by {@link ClientSession#withRenewal(Action) - * withRenewal()}. The action will be performed once, and if it fails with a - * permission fault, the session will be renewed and the action performed - * exactly once more. - * - * @param - * The type of the result of the action. - * @param - * The extra exceptions that may be thrown by the action. - */ - @FunctionalInterface - interface Action extends Callable { - /** - * Perform the action. - * - * @return The result of the action. - * @throws IOException - * If network I/O fails. - * @throws Exn - * If another failure happens. - */ - @Override - T call() throws Exn, IOException; - } - - /** - * Carry out an action, applying session renewal once if needed. - * - * @param - * The type of the return value. - * @param - * The extra exceptions that may be thrown by the action. - * @param action - * The action to be repeated if it fails due to session expiry. - * @return The result of the action - * @throws IOException - * If things go wrong. - * @throws Exn - * If another kind of failure happens. - */ - T withRenewal(Action action) - throws Exn, IOException; - - /** - * Discovers the root of a Spalloc service. Also sets up the true CSRF token - * handling. - * - * @return The service root information. - * @throws IOException - * If access fails. - */ - RootInfo discoverRoot() throws IOException; - - /** - * Connect a Spalloc proxy protocol websocket to the given URL. - * - * @param url - * Where the websocket connects. - * @return The connected websocket. - * @throws InterruptedException - * If interrupted during connection - * @throws IOException - * If there are network problems - * @throws RuntimeException - * For various reasons - */ - ProxyProtocolClient websocket(URI url) - throws InterruptedException, IOException; -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.client; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URLConnection; +import java.util.concurrent.Callable; + +/** + * Operations on the low level session that are intended to be used by the + * client. + */ +interface Session { + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, String url2, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, URI url2, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @return the connection, which should not be used to change the service + * state. + * @throws IOException + * If things go wrong + */ + default HttpURLConnection connection(URI url, URI url2) throws IOException { + return connection(url, url2, false); + } + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @return the connection, which should not be used to change the service + * state. + * @throws IOException + * If things go wrong + */ + default HttpURLConnection connection(URI url) throws IOException { + return connection(url, false); + } + + /** + * Check for and handle any session cookie changes. + *

+ * Assumes that the session key is in the {@code JSESSIONID} cookie. + * + * @param conn + * Connection that's had a transaction processed. + * @return Whether the session cookie was set. Normally uninteresting. + */ + boolean trackCookie(HttpURLConnection conn); + + /** + * An action used by {@link ClientSession#withRenewal(Action) + * withRenewal()}. The action will be performed once, and if it fails with a + * permission fault, the session will be renewed and the action performed + * exactly once more. + * + * @param + * The type of the result of the action. + * @param + * The extra exceptions that may be thrown by the action. + */ + @FunctionalInterface + interface Action extends Callable { + /** + * Perform the action. + * + * @return The result of the action. + * @throws IOException + * If network I/O fails. + * @throws Exn + * If another failure happens. + */ + @Override + T call() throws Exn, IOException; + } + + /** + * Carry out an action, applying session renewal once if needed. + * + * @param + * The type of the return value. + * @param + * The extra exceptions that may be thrown by the action. + * @param action + * The action to be repeated if it fails due to session expiry. + * @return The result of the action + * @throws IOException + * If things go wrong. + * @throws Exn + * If another kind of failure happens. + */ + T withRenewal(Action action) + throws Exn, IOException; + + /** + * Discovers the root of a Spalloc service. Also sets up the true CSRF token + * handling. + * + * @return The service root information. + * @throws IOException + * If access fails. + */ + RootInfo discoverRoot() throws IOException; + + /** + * Connect a Spalloc proxy protocol websocket to the given URL. + * + * @param url + * Where the websocket connects. + * @return The connected websocket. + * @throws InterruptedException + * If interrupted during connection + * @throws IOException + * If there are network problems + * @throws RuntimeException + * For various reasons + */ + ProxyProtocolClient websocket(URI url) + throws InterruptedException, IOException; +} 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 index 234a23c507..ec7873ad73 100644 --- 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 @@ -1,45 +1,45 @@ -/* - * 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 - * - * http://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; - } -} +/* + * 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 + * + * http://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/SerialVector.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java index 98849f8953..63bf50ec99 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/SerialVector.java @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.messages.scp.SCPCommand; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * The data in the serial vector. The result of a {@link SCPCommand#CMD_BMP_INFO - * BMP_INFO} call with argument {@link BMPInfo#SERIAL SERIAL}. - *

- * See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. - * - * @see ReadSerialVector - */ -@UsedInJavadocOnly(SCPCommand.class) -public class SerialVector { - /** The number of words in the {@link #getSerialNumber() serial_number}. */ - public static final int SERIAL_LENGTH = 4; - - /** Hardware version. */ - private final int hardwareVersion; - - /** LPC1768 serial number. Length 4. */ - private final IntBuffer serialNumber; - - /** Flash buffer address. */ - private final MemoryLocation flashBuffer; - - /** {@code board_stat} address for the board. */ - private final MemoryLocation boardStat; - - /** Cortex boot vector address. */ - private final MemoryLocation cortexBoot; - - /** - * @param buffer - * Where to deserialize the vector from. - */ - SerialVector(ByteBuffer buffer) { - var b = buffer.asIntBuffer(); - hardwareVersion = b.get(); - var sn = new int[SERIAL_LENGTH]; - b.get(sn); - serialNumber = IntBuffer.wrap(sn); - flashBuffer = new MemoryLocation(b.get()); - boardStat = new MemoryLocation(b.get()); - cortexBoot = new MemoryLocation(b.get()); - } - - /** @return The hardware version. */ - public int getHardwareVersion() { - return hardwareVersion; - } - - /** - * @return The device serial number, as a read-only buffer. - */ - // @formatter:off - /* Obtained from LPC17xx In Application Programming function 58. The API - * descriptions for these things are fairly well buried in the LPC17xx User - * Manual. This is the relevant part: - * - * Command Read device serial number - * Input Command code: 5810 - * Parameters: None - * Return Code CMD_SUCCESS | - * Result Result0: First 32-bit word of Device Identification Number - * (at the lowest address) - * Result1: Second 32-bit word of Device Identification Number - * Result2: Third 32-bit word of Device Identification Number - * Result3: Fourth 32-bit word of Device Identification Number - * Description This command is used to read the device identification - * number. The serial number may be used to uniquely identify - * a single unit among all LPC17xx devices. - * - * The four words of the result form the four words provided below, in the - * order described above (not that that typically matters). */ - // @formatter:on - public IntBuffer getSerialNumber() { - // Make a new instance so positions aren't shared - return serialNumber.asReadOnlyBuffer(); - } - - /** @return The location of the flash buffer. */ - public MemoryLocation getFlashBuffer() { - return flashBuffer; - } - - /** - * @return The board status block location. - * @see ReadADC - */ - public MemoryLocation getBoardStatusLocation() { - return boardStat; - } - - /** @return The location of the Cortex boot vector. */ - public MemoryLocation getCortexVector() { - return cortexBoot; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import uk.ac.manchester.spinnaker.machine.MemoryLocation; +import uk.ac.manchester.spinnaker.messages.scp.SCPCommand; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * The data in the serial vector. The result of a {@link SCPCommand#CMD_BMP_INFO + * BMP_INFO} call with argument {@link BMPInfo#SERIAL SERIAL}. + *

+ * See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. + * + * @see ReadSerialVector + */ +@UsedInJavadocOnly(SCPCommand.class) +public class SerialVector { + /** The number of words in the {@link #getSerialNumber() serial_number}. */ + public static final int SERIAL_LENGTH = 4; + + /** Hardware version. */ + private final int hardwareVersion; + + /** LPC1768 serial number. Length 4. */ + private final IntBuffer serialNumber; + + /** Flash buffer address. */ + private final MemoryLocation flashBuffer; + + /** {@code board_stat} address for the board. */ + private final MemoryLocation boardStat; + + /** Cortex boot vector address. */ + private final MemoryLocation cortexBoot; + + /** + * @param buffer + * Where to deserialize the vector from. + */ + SerialVector(ByteBuffer buffer) { + var b = buffer.asIntBuffer(); + hardwareVersion = b.get(); + var sn = new int[SERIAL_LENGTH]; + b.get(sn); + serialNumber = IntBuffer.wrap(sn); + flashBuffer = new MemoryLocation(b.get()); + boardStat = new MemoryLocation(b.get()); + cortexBoot = new MemoryLocation(b.get()); + } + + /** @return The hardware version. */ + public int getHardwareVersion() { + return hardwareVersion; + } + + /** + * @return The device serial number, as a read-only buffer. + */ + // @formatter:off + /* Obtained from LPC17xx In Application Programming function 58. The API + * descriptions for these things are fairly well buried in the LPC17xx User + * Manual. This is the relevant part: + * + * Command Read device serial number + * Input Command code: 5810 + * Parameters: None + * Return Code CMD_SUCCESS | + * Result Result0: First 32-bit word of Device Identification Number + * (at the lowest address) + * Result1: Second 32-bit word of Device Identification Number + * Result2: Third 32-bit word of Device Identification Number + * Result3: Fourth 32-bit word of Device Identification Number + * Description This command is used to read the device identification + * number. The serial number may be used to uniquely identify + * a single unit among all LPC17xx devices. + * + * The four words of the result form the four words provided below, in the + * order described above (not that that typically matters). */ + // @formatter:on + public IntBuffer getSerialNumber() { + // Make a new instance so positions aren't shared + return serialNumber.asReadOnlyBuffer(); + } + + /** @return The location of the flash buffer. */ + public MemoryLocation getFlashBuffer() { + return flashBuffer; + } + + /** + * @return The board status block location. + * @see ReadADC + */ + public MemoryLocation getBoardStatusLocation() { + return boardStat; + } + + /** @return The location of the Cortex boot vector. */ + public MemoryLocation getCortexVector() { + return cortexBoot; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java index 8bafb04bb8..7eaa937d89 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java @@ -1,39 +1,39 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import java.net.InetAddress; - -/** The IP addresses associated with a SpiNNaker board. */ -public final class Addresses { - // TODO convert to record in 17 - /** The IPv4 address of the BMP. */ - public final InetAddress bmpIPAddress; - - /** The IPv4 address of the managed SpiNNaker board. */ - public final InetAddress spinIPAddress; - - /** - * @param bmpIPAddress - * The IPv4 address of the BMP. - * @param spinIPAddress - * The IPv4 address of the managed SpiNNaker board. - */ - public Addresses(InetAddress bmpIPAddress, InetAddress spinIPAddress) { - this.bmpIPAddress = bmpIPAddress; - this.spinIPAddress = spinIPAddress; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import java.net.InetAddress; + +/** The IP addresses associated with a SpiNNaker board. */ +public final class Addresses { + // TODO convert to record in 17 + /** The IPv4 address of the BMP. */ + public final InetAddress bmpIPAddress; + + /** The IPv4 address of the managed SpiNNaker board. */ + public final InetAddress spinIPAddress; + + /** + * @param bmpIPAddress + * The IPv4 address of the BMP. + * @param spinIPAddress + * The IPv4 address of the managed SpiNNaker board. + */ + public Addresses(InetAddress bmpIPAddress, InetAddress spinIPAddress) { + this.bmpIPAddress = bmpIPAddress; + this.spinIPAddress = spinIPAddress; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index a3ea823764..bebe4ea655 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -1,554 +1,554 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import static java.lang.Integer.parseInt; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteBuffer.wrap; -import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Arrays.stream; -import static java.util.Collections.unmodifiableMap; -import static java.util.Collections.unmodifiableSet; -import static java.util.Objects.requireNonNull; -import static java.util.regex.Pattern.compile; -import static java.util.stream.Collectors.toMap; -import static java.util.stream.Collectors.toSet; -import static java.util.stream.IntStream.range; -import static org.apache.commons.io.IOUtils.buffer; -import static org.slf4j.LoggerFactory.getLogger; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_LINKS_PER_ROUTER; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_NUM_CORES; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.PROCESSORS_PER_CHIP; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_X_OF_ONE_BOARD; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_Y_OF_ONE_BOARD; -import static uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry.getSpinn5Geometry; -import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; -import static uk.ac.manchester.spinnaker.utils.CollectionUtils.OR; -import static uk.ac.manchester.spinnaker.utils.CollectionUtils.toEnumSet; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Formatter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.slf4j.Logger; - -import jakarta.validation.Valid; -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.machine.Direction; -import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; -import uk.ac.manchester.spinnaker.machine.ValidP; -import uk.ac.manchester.spinnaker.utils.CollectionUtils; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * A blacklist read off a board. Note that all chip coordinates are - * board-relative and all processor IDs are physical; the boot process applies - * blacklists before inter-board links are brought up and before the - * virtual-to-physical core mapping is established. - * - * @author Donal Fellows - */ -public final class Blacklist implements Serializable { - private static final long serialVersionUID = -7759940789892168209L; - - private static final Logger log = getLogger(Blacklist.class); - - private static final SpiNNakerTriadGeometry GEOM = getSpinn5Geometry(); - - private static final int SPINN5_CHIPS_PER_BOARD = 48; - - private static final int COORD_BITS = 3; - - private static final int COORD_MASK = (1 << COORD_BITS) - 1; - - private static final int CORE_MASK = (1 << MAX_NUM_CORES) - 1; - - private static final int LINK_MASK = (1 << MAX_LINKS_PER_ROUTER) - 1; - - private static final int PAYLOAD_BITS = - MAX_NUM_CORES + MAX_LINKS_PER_ROUTER; - - /** - * Bytes that represent the blacklist. Writability undefined. - * Endianness undefined. Position will be at the start of the - * blacklist data, which will be expected to run to the limit of the buffer - * (i.e., there are {@link Buffer#remaining()} bytes left). Access to this - * variable must be careful! - */ - @UsedInJavadocOnly(Buffer.class) - private transient ByteBuffer rawData; - - /** The blacklisted chips. */ - private Set<@Valid ChipLocation> chips = new HashSet<>(); - - /** The blacklisted cores. */ - private Map<@Valid ChipLocation, Set<@ValidP Integer>> cores = - new HashMap<>(); - - /** The blacklisted links. */ - private Map<@Valid ChipLocation, Set> links = new HashMap<>(); - - /** - * Create a blacklist from raw data. - * - * @param buffer - * The raw data to parse. - */ - public Blacklist(ByteBuffer buffer) { - var buf = requireNonNull(buffer).duplicate().order(LITTLE_ENDIAN); - rawData = buf.duplicate(); - decodeBlacklist(buf); - } - - /** - * Create a blacklist from parsed data. - * - * @param deadChips - * The set of chips that are dead. - * @param deadCores - * The set of physical core IDs that are dead on live chips. - * Should not contain any empty sets of physical core - * IDs; caller should ensure. - * @param deadLinks - * The set of link directions that are dead on live chips. - * Should not contain any empty sets of directions; - * caller should ensure. - */ - public Blacklist(Set deadChips, - Map> deadCores, - Map> deadLinks) { - chips = requireNonNull(deadChips); - // Sort the elements in each sub-collection - cores = requireNonNull(deadCores).entrySet().stream().collect( - toMap(Entry::getKey, e -> new TreeSet<>(e.getValue()))); - links = requireNonNull(deadLinks).entrySet().stream().collect( - toMap(Entry::getKey, e -> EnumSet.copyOf(e.getValue()))); - rawData = encodeBlacklist(); - } - - private ByteBuffer encodeBlacklist() { - var buf = allocate((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE) - .order(LITTLE_ENDIAN); - buf.putInt(0); // Size; filled in later - int count = 0; - for (int x = 0; x < SIZE_X_OF_ONE_BOARD; x++) { - for (int y = 0; y < SIZE_Y_OF_ONE_BOARD; y++) { - var chip = new ChipLocation(x, y); - int loc = (x << COORD_BITS) | y; - int value = 0; - if (chips.contains(chip)) { - value = CORE_MASK; - } else { - if (cores.containsKey(chip)) { - value |= cores.get(chip).stream() - .mapToInt(core -> 1 << core) // - .reduce(0, OR) & CORE_MASK; - } - if (links.containsKey(chip)) { - value |= links.get(chip).stream() - .mapToInt(linkDir -> 1 << linkDir.id) - .reduce(0, OR) << MAX_NUM_CORES; - } - } - if (value != 0) { - buf.putInt(value | loc << PAYLOAD_BITS); - count++; - } - } - } - buf.flip(); - buf.putInt(0, count); // Fill in the size now we know it - return buf; - } - - private void decodeBlacklist(ByteBuffer buf) { - var entries = buf.asIntBuffer(); - int len = entries.get(); - var done = new HashSet(); - - for (int i = 0; i < len; i++) { - int entry = entries.get(); - - // get board coordinates - int bx = (entry >> (PAYLOAD_BITS + COORD_BITS)) & COORD_MASK; - int by = (entry >> PAYLOAD_BITS) & COORD_MASK; - var b = new ChipLocation(bx, by); - - // check for repeated coordinates - if (done.contains(b)) { - log.warn("duplicate chip in blacklist file: {},{}", bx, by); - } - done.add(b); - - /* - * Check for blacklisted chips; those are the ones where all cores - * are blacklisted so no monitor is safe to bring up. - */ - int mcl = entry & CORE_MASK; - if (mcl == CORE_MASK) { - chips.add(b); - } else if (mcl != 0) { - // check for blacklisted cores - cores.put(b, - range(0, MAX_NUM_CORES) - .filter(c -> (mcl & (1 << c)) != 0) - .mapToObj(Integer::valueOf).collect(toSet())); - // check for blacklisted links - int mll = (entry >> MAX_NUM_CORES) & LINK_MASK; - if (mll != 0) { - links.put(b, - range(0, MAX_LINKS_PER_ROUTER) - .filter(c -> (mll & (1 << c)) != 0) - .mapToObj(Direction::byId) - .collect(toEnumSet(Direction.class))); - } - } - } - } - - /** - * Create a blacklist from a string. - * - * @param blacklistText - * The string to parse. - * @throws IllegalArgumentException - * If the string is badly formatted. - */ - public Blacklist(String blacklistText) { - requireNonNull(blacklistText, "blacklist text should not be null") - .lines().map(String::strip) - // Remove blank and comment lines - .filter(Blacklist::isRelevantLine) - // Parse the remaining lines - .forEach(this::parseLine); - rawData = encodeBlacklist(); - } - - /** - * Create a blacklist from a text file. - * - * @param blacklistFile - * The file to parse. - * @throws IOException - * If the file can't be read from. - * @throws IllegalArgumentException - * If the string is badly formatted. - */ - public Blacklist(File blacklistFile) throws IOException { - try (var r = - buffer(new FileReader( - requireNonNull(blacklistFile, - "blacklist filename should not be null"), - UTF_8))) { - r.lines().map(String::strip) - // Remove blank and comment lines - .filter(Blacklist::isRelevantLine) - // Parse the remaining lines - .forEach(this::parseLine); - rawData = encodeBlacklist(); - } - } - - private static boolean isRelevantLine(String s) { - return !s.isBlank() && !s.startsWith("#"); - } - - // REs from Perl code to read blacklist files - - private static final Pattern CHIP_PATTERN = compile( - "^\\s*chip\\s+(?[0-7])\\s+(?[0-7])\\s*"); - - private static final Pattern CORE_PATTERN = compile( - "core\\s+(?\\S+)\\s*"); - - private static final Pattern LINK_PATTERN = compile( - "link\\s+(?\\S+)\\s*"); - - private static final Pattern DEAD_PATTERN = compile("dead\\s*"); - - private static String deleteMatched(Matcher m) { - var sb = new StringBuilder(); - m.appendReplacement(sb, "").appendTail(sb); - return sb.toString(); - } - - private static Set parseCommaSeparatedSet(String str) { - return CollectionUtils.parseCommaSeparatedSet(str, Integer::parseInt); - } - - private static > Set parseCommaSeparatedSet( - String str, Function fun, Class cls) { - return stream(str.split(",")).map(Integer::parseInt).map(fun) - .collect(toEnumSet(cls)); - } - - /** - * Parse one non-empty non-comment line of a blacklist file. - * - * @param line - * The line's contents. - * @throws IllegalArgumentException - * On most parse errors. - * @throws ArrayIndexOutOfBoundsException - * On a bad direction. - */ - private void parseLine(String line) { - var m = CHIP_PATTERN.matcher(line); - if (!m.find()) { - throw new IllegalArgumentException("bad line: " + line); - } - int x = parseInt(m.group("x")); - int y = parseInt(m.group("y")); - var chip = new ChipLocation(x, y); - if (!GEOM.singleBoard().contains(chip)) { - throw new IllegalArgumentException("bad chip coords: " + line); - } - var rest = deleteMatched(m); - - ChipLocation dead = null; - Set deadCores = null; - Set deadLinks = null; - - // Look for patterns at start of line while we can - while (true) { - m = CORE_PATTERN.matcher(rest); - if (m.find() && deadCores == null) { - deadCores = parseCommaSeparatedSet(m.group("cores")); - deadCores.forEach(c -> { - if (c < 0 || c >= PROCESSORS_PER_CHIP) { - throw new IllegalArgumentException( - "bad core number: " + line); - } - }); - rest = deleteMatched(m); - continue; - } - - m = LINK_PATTERN.matcher(rest); - if (m.find() && deadLinks == null) { - deadLinks = parseCommaSeparatedSet(m.group("links"), - Direction::byId, Direction.class); - rest = deleteMatched(m); - continue; - } - - m = DEAD_PATTERN.matcher(rest); - if (m.find() && dead == null) { - dead = chip; - rest = deleteMatched(m); - continue; - } - - // All done, or error - if (!rest.isBlank()) { - // Bad line - throw new IllegalArgumentException("bad line: " + line); - } - break; - } - - if (dead != null) { - chips.add(dead); - // Mask any info from lines defined above this one - cores.remove(dead); - links.remove(dead); - } else if (!chips.contains(chip)) { - if (deadCores != null && !deadCores.isEmpty()) { - cores.computeIfAbsent(chip, __ -> new HashSet<>()) - .addAll(deadCores); - } - if (deadLinks != null && !deadLinks.isEmpty()) { - links.computeIfAbsent(chip, - __ -> EnumSet.noneOf(Direction.class)) - .addAll(deadLinks); - } - } - } - - /** - * Convert the blacklist to a string in a human-readable format. This is the - * format understood by {@link #Blacklist(String)}. - *

- * Note that the result may omit information in the original blacklist, but - * only if that would also be ignored by the string parser. - * - * @return The string form of the blacklist. - * @throws RuntimeException - * If something goes wrong. Not expected! - */ - public String render() { - try (var f = new Formatter()) { - render(f); - return f.toString(); - } - } - - private void render(Formatter out) { - for (var chip : GEOM.singleBoard()) { - if (!isChipMentioned(chip)) { - continue; - } - out.format("chip %d %d", chip.getX(), chip.getY()); - if (chips.contains(chip)) { - out.format(" dead\n"); - } else { - if (cores.containsKey(chip)) { - out.format(" core "); - var sep = ""; - for (var id : cores.get(chip)) { - out.format(sep).format(id.toString()); - sep = ","; - } - } - if (links.containsKey(chip)) { - out.format(" link "); - var sep = ""; - for (var d : links.get(chip)) { - out.format(sep).format(Integer.toString(d.id)); - sep = ","; - } - } - out.format("\n"); - } - } - } - - /** - * @return The chips on the board that are blacklisted. A chip being - * blacklisted means that its links will also be blacklisted. - */ - public Set getChips() { - return unmodifiableSet(chips); - } - - /** - * @return The cores on the board that are blacklisted where the whole chip - * is not blacklisted. Note that these are physical - * processor IDs, not logical ones. - */ - public Map> getCores() { - return unmodifiableMap(cores); - } - - /** - * @return The links on the board that are blacklisted. - */ - public Map> getLinks() { - return unmodifiableMap(links); - } - - /** - * Test if a chip is known about by the blacklist. - * - * @param chip - * The chip to look for. Coordinates must be board-local. - * @return Whether the chip is mentioned in the blacklist. That could be if - * it is blacklisted, if it has a blacklisted core, of if one of its - * links is blacklisted. - */ - public boolean isChipMentioned(ChipLocation chip) { - return chips.contains(chip) || cores.containsKey(chip) - || links.containsKey(chip); - } - - /** @return The raw blacklist data in little-endian form. Read only. */ - public ByteBuffer getRawData() { - return rawData.asReadOnlyBuffer().order(LITTLE_ENDIAN); - } - - @Override - public int hashCode() { - return Objects.hash(chips, cores, links); - } - - @Override - public boolean equals(Object object) { - if (object instanceof Blacklist) { - var other = (Blacklist) object; - return chips.equals(other.chips) && cores.equals(other.cores) - && links.equals(other.links); - } - return false; - } - - @Override - public String toString() { - var s = new StringBuilder("Blacklist("); - s.append(chips).append(", ").append(cores).append(", ").append(links); - return s.append(")").toString(); - } - - /** - * Write this object to the stream. This is standard except for the special - * handling of the raw data. - * - * @param out - * Where to write to. - * @throws IOException - * If output fails. - * @see ObjectOutputStream#defaultWriteObject() - */ - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeInt(rawData.remaining()); - if (rawData.hasArray()) { - out.write(rawData.array(), rawData.position(), rawData.remaining()); - } else { - byte[] buf = new byte[rawData.remaining()]; - rawData.duplicate().get(buf); - out.write(buf); - } - } - - /** - * Set this object up by reading from the stream. This is standard except - * for the special handling of the raw data. - * - * @param in - * Where to read from. - * @throws IOException - * If input fails. - * @throws ClassNotFoundException - * if the class of a serialized object could not be found. - * @see ObjectInputStream#defaultReadObject() - */ - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - int len = in.readInt(); - var buf = new byte[len]; - in.read(buf); - rawData = wrap(buf).order(LITTLE_ENDIAN); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import static java.lang.Integer.parseInt; +import static java.nio.ByteBuffer.allocate; +import static java.nio.ByteBuffer.wrap; +import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.stream; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.Objects.requireNonNull; +import static java.util.regex.Pattern.compile; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.IntStream.range; +import static org.apache.commons.io.IOUtils.buffer; +import static org.slf4j.LoggerFactory.getLogger; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_LINKS_PER_ROUTER; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_NUM_CORES; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.PROCESSORS_PER_CHIP; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_X_OF_ONE_BOARD; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_Y_OF_ONE_BOARD; +import static uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry.getSpinn5Geometry; +import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; +import static uk.ac.manchester.spinnaker.utils.CollectionUtils.OR; +import static uk.ac.manchester.spinnaker.utils.CollectionUtils.toEnumSet; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Formatter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; + +import jakarta.validation.Valid; +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.machine.Direction; +import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; +import uk.ac.manchester.spinnaker.machine.ValidP; +import uk.ac.manchester.spinnaker.utils.CollectionUtils; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * A blacklist read off a board. Note that all chip coordinates are + * board-relative and all processor IDs are physical; the boot process applies + * blacklists before inter-board links are brought up and before the + * virtual-to-physical core mapping is established. + * + * @author Donal Fellows + */ +public final class Blacklist implements Serializable { + private static final long serialVersionUID = -7759940789892168209L; + + private static final Logger log = getLogger(Blacklist.class); + + private static final SpiNNakerTriadGeometry GEOM = getSpinn5Geometry(); + + private static final int SPINN5_CHIPS_PER_BOARD = 48; + + private static final int COORD_BITS = 3; + + private static final int COORD_MASK = (1 << COORD_BITS) - 1; + + private static final int CORE_MASK = (1 << MAX_NUM_CORES) - 1; + + private static final int LINK_MASK = (1 << MAX_LINKS_PER_ROUTER) - 1; + + private static final int PAYLOAD_BITS = + MAX_NUM_CORES + MAX_LINKS_PER_ROUTER; + + /** + * Bytes that represent the blacklist. Writability undefined. + * Endianness undefined. Position will be at the start of the + * blacklist data, which will be expected to run to the limit of the buffer + * (i.e., there are {@link Buffer#remaining()} bytes left). Access to this + * variable must be careful! + */ + @UsedInJavadocOnly(Buffer.class) + private transient ByteBuffer rawData; + + /** The blacklisted chips. */ + private Set<@Valid ChipLocation> chips = new HashSet<>(); + + /** The blacklisted cores. */ + private Map<@Valid ChipLocation, Set<@ValidP Integer>> cores = + new HashMap<>(); + + /** The blacklisted links. */ + private Map<@Valid ChipLocation, Set> links = new HashMap<>(); + + /** + * Create a blacklist from raw data. + * + * @param buffer + * The raw data to parse. + */ + public Blacklist(ByteBuffer buffer) { + var buf = requireNonNull(buffer).duplicate().order(LITTLE_ENDIAN); + rawData = buf.duplicate(); + decodeBlacklist(buf); + } + + /** + * Create a blacklist from parsed data. + * + * @param deadChips + * The set of chips that are dead. + * @param deadCores + * The set of physical core IDs that are dead on live chips. + * Should not contain any empty sets of physical core + * IDs; caller should ensure. + * @param deadLinks + * The set of link directions that are dead on live chips. + * Should not contain any empty sets of directions; + * caller should ensure. + */ + public Blacklist(Set deadChips, + Map> deadCores, + Map> deadLinks) { + chips = requireNonNull(deadChips); + // Sort the elements in each sub-collection + cores = requireNonNull(deadCores).entrySet().stream().collect( + toMap(Entry::getKey, e -> new TreeSet<>(e.getValue()))); + links = requireNonNull(deadLinks).entrySet().stream().collect( + toMap(Entry::getKey, e -> EnumSet.copyOf(e.getValue()))); + rawData = encodeBlacklist(); + } + + private ByteBuffer encodeBlacklist() { + var buf = allocate((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE) + .order(LITTLE_ENDIAN); + buf.putInt(0); // Size; filled in later + int count = 0; + for (int x = 0; x < SIZE_X_OF_ONE_BOARD; x++) { + for (int y = 0; y < SIZE_Y_OF_ONE_BOARD; y++) { + var chip = new ChipLocation(x, y); + int loc = (x << COORD_BITS) | y; + int value = 0; + if (chips.contains(chip)) { + value = CORE_MASK; + } else { + if (cores.containsKey(chip)) { + value |= cores.get(chip).stream() + .mapToInt(core -> 1 << core) // + .reduce(0, OR) & CORE_MASK; + } + if (links.containsKey(chip)) { + value |= links.get(chip).stream() + .mapToInt(linkDir -> 1 << linkDir.id) + .reduce(0, OR) << MAX_NUM_CORES; + } + } + if (value != 0) { + buf.putInt(value | loc << PAYLOAD_BITS); + count++; + } + } + } + buf.flip(); + buf.putInt(0, count); // Fill in the size now we know it + return buf; + } + + private void decodeBlacklist(ByteBuffer buf) { + var entries = buf.asIntBuffer(); + int len = entries.get(); + var done = new HashSet(); + + for (int i = 0; i < len; i++) { + int entry = entries.get(); + + // get board coordinates + int bx = (entry >> (PAYLOAD_BITS + COORD_BITS)) & COORD_MASK; + int by = (entry >> PAYLOAD_BITS) & COORD_MASK; + var b = new ChipLocation(bx, by); + + // check for repeated coordinates + if (done.contains(b)) { + log.warn("duplicate chip in blacklist file: {},{}", bx, by); + } + done.add(b); + + /* + * Check for blacklisted chips; those are the ones where all cores + * are blacklisted so no monitor is safe to bring up. + */ + int mcl = entry & CORE_MASK; + if (mcl == CORE_MASK) { + chips.add(b); + } else if (mcl != 0) { + // check for blacklisted cores + cores.put(b, + range(0, MAX_NUM_CORES) + .filter(c -> (mcl & (1 << c)) != 0) + .mapToObj(Integer::valueOf).collect(toSet())); + // check for blacklisted links + int mll = (entry >> MAX_NUM_CORES) & LINK_MASK; + if (mll != 0) { + links.put(b, + range(0, MAX_LINKS_PER_ROUTER) + .filter(c -> (mll & (1 << c)) != 0) + .mapToObj(Direction::byId) + .collect(toEnumSet(Direction.class))); + } + } + } + } + + /** + * Create a blacklist from a string. + * + * @param blacklistText + * The string to parse. + * @throws IllegalArgumentException + * If the string is badly formatted. + */ + public Blacklist(String blacklistText) { + requireNonNull(blacklistText, "blacklist text should not be null") + .lines().map(String::strip) + // Remove blank and comment lines + .filter(Blacklist::isRelevantLine) + // Parse the remaining lines + .forEach(this::parseLine); + rawData = encodeBlacklist(); + } + + /** + * Create a blacklist from a text file. + * + * @param blacklistFile + * The file to parse. + * @throws IOException + * If the file can't be read from. + * @throws IllegalArgumentException + * If the string is badly formatted. + */ + public Blacklist(File blacklistFile) throws IOException { + try (var r = + buffer(new FileReader( + requireNonNull(blacklistFile, + "blacklist filename should not be null"), + UTF_8))) { + r.lines().map(String::strip) + // Remove blank and comment lines + .filter(Blacklist::isRelevantLine) + // Parse the remaining lines + .forEach(this::parseLine); + rawData = encodeBlacklist(); + } + } + + private static boolean isRelevantLine(String s) { + return !s.isBlank() && !s.startsWith("#"); + } + + // REs from Perl code to read blacklist files + + private static final Pattern CHIP_PATTERN = compile( + "^\\s*chip\\s+(?[0-7])\\s+(?[0-7])\\s*"); + + private static final Pattern CORE_PATTERN = compile( + "core\\s+(?\\S+)\\s*"); + + private static final Pattern LINK_PATTERN = compile( + "link\\s+(?\\S+)\\s*"); + + private static final Pattern DEAD_PATTERN = compile("dead\\s*"); + + private static String deleteMatched(Matcher m) { + var sb = new StringBuilder(); + m.appendReplacement(sb, "").appendTail(sb); + return sb.toString(); + } + + private static Set parseCommaSeparatedSet(String str) { + return CollectionUtils.parseCommaSeparatedSet(str, Integer::parseInt); + } + + private static > Set parseCommaSeparatedSet( + String str, Function fun, Class cls) { + return stream(str.split(",")).map(Integer::parseInt).map(fun) + .collect(toEnumSet(cls)); + } + + /** + * Parse one non-empty non-comment line of a blacklist file. + * + * @param line + * The line's contents. + * @throws IllegalArgumentException + * On most parse errors. + * @throws ArrayIndexOutOfBoundsException + * On a bad direction. + */ + private void parseLine(String line) { + var m = CHIP_PATTERN.matcher(line); + if (!m.find()) { + throw new IllegalArgumentException("bad line: " + line); + } + int x = parseInt(m.group("x")); + int y = parseInt(m.group("y")); + var chip = new ChipLocation(x, y); + if (!GEOM.singleBoard().contains(chip)) { + throw new IllegalArgumentException("bad chip coords: " + line); + } + var rest = deleteMatched(m); + + ChipLocation dead = null; + Set deadCores = null; + Set deadLinks = null; + + // Look for patterns at start of line while we can + while (true) { + m = CORE_PATTERN.matcher(rest); + if (m.find() && deadCores == null) { + deadCores = parseCommaSeparatedSet(m.group("cores")); + deadCores.forEach(c -> { + if (c < 0 || c >= PROCESSORS_PER_CHIP) { + throw new IllegalArgumentException( + "bad core number: " + line); + } + }); + rest = deleteMatched(m); + continue; + } + + m = LINK_PATTERN.matcher(rest); + if (m.find() && deadLinks == null) { + deadLinks = parseCommaSeparatedSet(m.group("links"), + Direction::byId, Direction.class); + rest = deleteMatched(m); + continue; + } + + m = DEAD_PATTERN.matcher(rest); + if (m.find() && dead == null) { + dead = chip; + rest = deleteMatched(m); + continue; + } + + // All done, or error + if (!rest.isBlank()) { + // Bad line + throw new IllegalArgumentException("bad line: " + line); + } + break; + } + + if (dead != null) { + chips.add(dead); + // Mask any info from lines defined above this one + cores.remove(dead); + links.remove(dead); + } else if (!chips.contains(chip)) { + if (deadCores != null && !deadCores.isEmpty()) { + cores.computeIfAbsent(chip, __ -> new HashSet<>()) + .addAll(deadCores); + } + if (deadLinks != null && !deadLinks.isEmpty()) { + links.computeIfAbsent(chip, + __ -> EnumSet.noneOf(Direction.class)) + .addAll(deadLinks); + } + } + } + + /** + * Convert the blacklist to a string in a human-readable format. This is the + * format understood by {@link #Blacklist(String)}. + *

+ * Note that the result may omit information in the original blacklist, but + * only if that would also be ignored by the string parser. + * + * @return The string form of the blacklist. + * @throws RuntimeException + * If something goes wrong. Not expected! + */ + public String render() { + try (var f = new Formatter()) { + render(f); + return f.toString(); + } + } + + private void render(Formatter out) { + for (var chip : GEOM.singleBoard()) { + if (!isChipMentioned(chip)) { + continue; + } + out.format("chip %d %d", chip.getX(), chip.getY()); + if (chips.contains(chip)) { + out.format(" dead\n"); + } else { + if (cores.containsKey(chip)) { + out.format(" core "); + var sep = ""; + for (var id : cores.get(chip)) { + out.format(sep).format(id.toString()); + sep = ","; + } + } + if (links.containsKey(chip)) { + out.format(" link "); + var sep = ""; + for (var d : links.get(chip)) { + out.format(sep).format(Integer.toString(d.id)); + sep = ","; + } + } + out.format("\n"); + } + } + } + + /** + * @return The chips on the board that are blacklisted. A chip being + * blacklisted means that its links will also be blacklisted. + */ + public Set getChips() { + return unmodifiableSet(chips); + } + + /** + * @return The cores on the board that are blacklisted where the whole chip + * is not blacklisted. Note that these are physical + * processor IDs, not logical ones. + */ + public Map> getCores() { + return unmodifiableMap(cores); + } + + /** + * @return The links on the board that are blacklisted. + */ + public Map> getLinks() { + return unmodifiableMap(links); + } + + /** + * Test if a chip is known about by the blacklist. + * + * @param chip + * The chip to look for. Coordinates must be board-local. + * @return Whether the chip is mentioned in the blacklist. That could be if + * it is blacklisted, if it has a blacklisted core, of if one of its + * links is blacklisted. + */ + public boolean isChipMentioned(ChipLocation chip) { + return chips.contains(chip) || cores.containsKey(chip) + || links.containsKey(chip); + } + + /** @return The raw blacklist data in little-endian form. Read only. */ + public ByteBuffer getRawData() { + return rawData.asReadOnlyBuffer().order(LITTLE_ENDIAN); + } + + @Override + public int hashCode() { + return Objects.hash(chips, cores, links); + } + + @Override + public boolean equals(Object object) { + if (object instanceof Blacklist) { + var other = (Blacklist) object; + return chips.equals(other.chips) && cores.equals(other.cores) + && links.equals(other.links); + } + return false; + } + + @Override + public String toString() { + var s = new StringBuilder("Blacklist("); + s.append(chips).append(", ").append(cores).append(", ").append(links); + return s.append(")").toString(); + } + + /** + * Write this object to the stream. This is standard except for the special + * handling of the raw data. + * + * @param out + * Where to write to. + * @throws IOException + * If output fails. + * @see ObjectOutputStream#defaultWriteObject() + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(rawData.remaining()); + if (rawData.hasArray()) { + out.write(rawData.array(), rawData.position(), rawData.remaining()); + } else { + byte[] buf = new byte[rawData.remaining()]; + rawData.duplicate().get(buf); + out.write(buf); + } + } + + /** + * Set this object up by reading from the stream. This is standard except + * for the special handling of the raw data. + * + * @param in + * Where to read from. + * @throws IOException + * If input fails. + * @throws ClassNotFoundException + * if the class of a serialized object could not be found. + * @see ObjectInputStream#defaultReadObject() + */ + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + int len = in.readInt(); + var buf = new byte[len]; + in.read(buf); + rawData = wrap(buf).order(LITTLE_ENDIAN); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java index 234e3fddfd..74deb0550c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java @@ -1,179 +1,179 @@ -/* - * Copyright (c) 2018-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 - * - * http://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.model; - -import static java.net.InetAddress.getByAddress; -import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.CORE_MASK; -import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.PORT_SHIFT; -import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.THREE_BITS_MASK; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.machine.CoreLocation; -import uk.ac.manchester.spinnaker.machine.HasChipLocation; -import uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.machine.tags.IPTag; -import uk.ac.manchester.spinnaker.machine.tags.ReverseIPTag; -import uk.ac.manchester.spinnaker.machine.tags.Tag; - -/** Description of a tag. */ -public final class TagDescription { - // TODO convert to a record in Java 17 - /** - * The count of the number of packets that have been sent with the tag. - */ - public final int count; - - /** The flags of the tag. */ - public final short flags; - - /** The IP address of the tag. */ - public final InetAddress ipAddress; - - /** The MAC address of the tag, as an array of 6 bytes. */ - public final byte[] macAddress; - - /** The port of the tag. */ - public final int port; - - /** The receive port of the tag. */ - public final int rxPort; - - /** - * The location of the core on the chip which the tag is defined on and - * where the core that handles the tag's messages resides. - */ - public final HasCoreLocation spinCore; - - /** The spin-port of the IP tag. */ - public final int spinPort; - - /** The timeout of the tag. */ - public final IPTagTimeOutWaitTime timeout; - - /** Where did the message that we've parsed this from originate from? */ - private final ChipLocation src; - - /** - * On what SpiNNaker board did this info originate? Assumes we were talking - * directly to the board. - */ - private final InetAddress host; - - /** What tag was this info about? */ - private final int tag; - - /** - * @param buffer - * The buffer to parse. - * @param src - * What chip did this come from? - * @param host - * What address did that chip have? (Only for creating a - * {@link Tag}.) - * @param tag - * What was the tag ID? (Only for creating a {@link Tag}.) - * @throws UnknownHostException - * If we can't parse the host. Unexpected. - */ - public TagDescription(ByteBuffer buffer, HasChipLocation src, - InetAddress host, int tag) throws UnknownHostException { - byte[] ipBytes = new byte[IPV4_BYTES]; - buffer.get(ipBytes); - ipAddress = getByAddress(ipBytes); - - macAddress = new byte[MAC_BYTES]; - buffer.get(macAddress); - - port = Short.toUnsignedInt(buffer.getShort()); - timeout = IPTagTimeOutWaitTime.get(buffer.getShort()); - flags = buffer.getShort(); - count = buffer.getInt(); - rxPort = Short.toUnsignedInt(buffer.getShort()); - int y = Byte.toUnsignedInt(buffer.get()); - int x = Byte.toUnsignedInt(buffer.get()); - int pp = Byte.toUnsignedInt(buffer.get()); - spinCore = new CoreLocation(x, y, pp & CORE_MASK); - spinPort = (pp >>> PORT_SHIFT) & THREE_BITS_MASK; - this.src = src.asChipLocation(); - this.host = host; - this.tag = tag; - } - - private static final int IPV4_BYTES = 4; - - private static final int MAC_BYTES = 6; - - private static final int USE_BIT = 15; - - private static final int TEMP_BIT = 14; - - private static final int ARP_BIT = 13; - - private static final int REV_BIT = 9; - - private static final int STRIP_BIT = 8; - - private boolean bitset(int bit) { - return (flags & (1 << bit)) != 0; - } - - /** @return True if the tag is marked as being in use. */ - public boolean isInUse() { - return bitset(USE_BIT); - } - - /** @return True if the tag is temporary. */ - public boolean isTemporary() { - return bitset(TEMP_BIT); - } - - /** - * @return True if the tag is in the ARP state (where the MAC address is - * being looked up; this is a transient state so unlikely). - */ - public boolean isARP() { - return bitset(ARP_BIT); - } - - /** @return True if the tag is a reverse tag. */ - public boolean isReverse() { - return bitset(REV_BIT); - } - - /** @return True if the tag is to strip the SDP header. */ - public boolean isStrippingSDP() { - return bitset(STRIP_BIT); - } - - /** - * Get the standard tag descriptor. Not properly meaningful unless the tag - * is {@linkplain #isInUse() in use}. - * - * @return The tag descriptor. May be an {@link IPTag} or a - * {@link ReverseIPTag}. - */ - public Tag getTag() { - if (isReverse()) { - return new ReverseIPTag(host, tag, rxPort, spinCore, spinPort); - } else { - return new IPTag(host, src, tag, ipAddress, port, isStrippingSDP()); - } - } -} +/* + * Copyright (c) 2018-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 + * + * http://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.model; + +import static java.net.InetAddress.getByAddress; +import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.CORE_MASK; +import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.PORT_SHIFT; +import static uk.ac.manchester.spinnaker.messages.model.IPTagFieldDefinitions.THREE_BITS_MASK; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.machine.CoreLocation; +import uk.ac.manchester.spinnaker.machine.HasChipLocation; +import uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.machine.tags.IPTag; +import uk.ac.manchester.spinnaker.machine.tags.ReverseIPTag; +import uk.ac.manchester.spinnaker.machine.tags.Tag; + +/** Description of a tag. */ +public final class TagDescription { + // TODO convert to a record in Java 17 + /** + * The count of the number of packets that have been sent with the tag. + */ + public final int count; + + /** The flags of the tag. */ + public final short flags; + + /** The IP address of the tag. */ + public final InetAddress ipAddress; + + /** The MAC address of the tag, as an array of 6 bytes. */ + public final byte[] macAddress; + + /** The port of the tag. */ + public final int port; + + /** The receive port of the tag. */ + public final int rxPort; + + /** + * The location of the core on the chip which the tag is defined on and + * where the core that handles the tag's messages resides. + */ + public final HasCoreLocation spinCore; + + /** The spin-port of the IP tag. */ + public final int spinPort; + + /** The timeout of the tag. */ + public final IPTagTimeOutWaitTime timeout; + + /** Where did the message that we've parsed this from originate from? */ + private final ChipLocation src; + + /** + * On what SpiNNaker board did this info originate? Assumes we were talking + * directly to the board. + */ + private final InetAddress host; + + /** What tag was this info about? */ + private final int tag; + + /** + * @param buffer + * The buffer to parse. + * @param src + * What chip did this come from? + * @param host + * What address did that chip have? (Only for creating a + * {@link Tag}.) + * @param tag + * What was the tag ID? (Only for creating a {@link Tag}.) + * @throws UnknownHostException + * If we can't parse the host. Unexpected. + */ + public TagDescription(ByteBuffer buffer, HasChipLocation src, + InetAddress host, int tag) throws UnknownHostException { + byte[] ipBytes = new byte[IPV4_BYTES]; + buffer.get(ipBytes); + ipAddress = getByAddress(ipBytes); + + macAddress = new byte[MAC_BYTES]; + buffer.get(macAddress); + + port = Short.toUnsignedInt(buffer.getShort()); + timeout = IPTagTimeOutWaitTime.get(buffer.getShort()); + flags = buffer.getShort(); + count = buffer.getInt(); + rxPort = Short.toUnsignedInt(buffer.getShort()); + int y = Byte.toUnsignedInt(buffer.get()); + int x = Byte.toUnsignedInt(buffer.get()); + int pp = Byte.toUnsignedInt(buffer.get()); + spinCore = new CoreLocation(x, y, pp & CORE_MASK); + spinPort = (pp >>> PORT_SHIFT) & THREE_BITS_MASK; + this.src = src.asChipLocation(); + this.host = host; + this.tag = tag; + } + + private static final int IPV4_BYTES = 4; + + private static final int MAC_BYTES = 6; + + private static final int USE_BIT = 15; + + private static final int TEMP_BIT = 14; + + private static final int ARP_BIT = 13; + + private static final int REV_BIT = 9; + + private static final int STRIP_BIT = 8; + + private boolean bitset(int bit) { + return (flags & (1 << bit)) != 0; + } + + /** @return True if the tag is marked as being in use. */ + public boolean isInUse() { + return bitset(USE_BIT); + } + + /** @return True if the tag is temporary. */ + public boolean isTemporary() { + return bitset(TEMP_BIT); + } + + /** + * @return True if the tag is in the ARP state (where the MAC address is + * being looked up; this is a transient state so unlikely). + */ + public boolean isARP() { + return bitset(ARP_BIT); + } + + /** @return True if the tag is a reverse tag. */ + public boolean isReverse() { + return bitset(REV_BIT); + } + + /** @return True if the tag is to strip the SDP header. */ + public boolean isStrippingSDP() { + return bitset(STRIP_BIT); + } + + /** + * Get the standard tag descriptor. Not properly meaningful unless the tag + * is {@linkplain #isInUse() in use}. + * + * @return The tag descriptor. May be an {@link IPTag} or a + * {@link ReverseIPTag}. + */ + public Tag getTag() { + if (isReverse()) { + return new ReverseIPTag(host, tag, rxPort, spinCore, spinPort); + } else { + return new IPTag(host, src, tag, ipAddress, port, isStrippingSDP()); + } + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java index 60d2a820ae..dee2c8104f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2018-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 - * - * http://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.model; - -import com.google.errorprone.annotations.Immutable; - -/** Information about a tag pool on an Ethernet-connected chip. */ -@Immutable -public final class TagInfo { - /** - * The timeout for transient IP tags (i.e., responses to SCP commands). - */ - public final IPTagTimeOutWaitTime transientTimeout; - - /** The count of the IP tag pool size. */ - public final int poolSize; - - /** The count of the number of fixed IP tag entries. */ - public final int fixedSize; - - /** - * @param transientTimeout - * The timeout for transient IP tags (i.e., responses to SCP - * commands). - * @param poolSize - * The count of the IP tag pool size. - * @param fixedSize - * The count of the number of fixed IP tag entries. - */ - public TagInfo(IPTagTimeOutWaitTime transientTimeout, int poolSize, - int fixedSize) { - this.transientTimeout = transientTimeout; - this.poolSize = poolSize; - this.fixedSize = fixedSize; - } -} +/* + * Copyright (c) 2018-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 + * + * http://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.model; + +import com.google.errorprone.annotations.Immutable; + +/** Information about a tag pool on an Ethernet-connected chip. */ +@Immutable +public final class TagInfo { + /** + * The timeout for transient IP tags (i.e., responses to SCP commands). + */ + public final IPTagTimeOutWaitTime transientTimeout; + + /** The count of the IP tag pool size. */ + public final int poolSize; + + /** The count of the number of fixed IP tag entries. */ + public final int fixedSize; + + /** + * @param transientTimeout + * The timeout for transient IP tags (i.e., responses to SCP + * commands). + * @param poolSize + * The count of the IP tag pool size. + * @param fixedSize + * The count of the number of fixed IP tag entries. + */ + public TagInfo(IPTagTimeOutWaitTime transientTimeout, int poolSize, + int fixedSize) { + this.transientTimeout = transientTimeout; + this.poolSize = poolSize; + this.fixedSize = fixedSize; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java index 435c5000e6..d55231af20 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import uk.ac.manchester.spinnaker.messages.scp.SCPResult; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * Indicate that the board (or BMP) was unable to send a message on to its - * final destination. - */ -public class UnroutableMessageException - extends UnexpectedResponseCodeException { - private static final long serialVersionUID = 2106128799950032057L; - - /** The full header from the response message. */ - public final SDPHeader header; - - /** - * @param operation - * The overall operation that we were doing. - * @param command - * The command that we were handling a response to. - * @param header - * The header that indicated a problem with routing. - */ - public UnroutableMessageException(String operation, Enum command, - SDPHeader header) { - super(operation, command, SCPResult.RC_ROUTE); - this.header = header; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import uk.ac.manchester.spinnaker.messages.scp.SCPResult; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * Indicate that the board (or BMP) was unable to send a message on to its + * final destination. + */ +public class UnroutableMessageException + extends UnexpectedResponseCodeException { + private static final long serialVersionUID = 2106128799950032057L; + + /** The full header from the response message. */ + public final SDPHeader header; + + /** + * @param operation + * The overall operation that we were doing. + * @param command + * The command that we were handling a response to. + * @param header + * The header that indicated a problem with routing. + */ + public UnroutableMessageException(String operation, Enum command, + SDPHeader header) { + super(operation, command, SCPResult.RC_ROUTE); + this.header = header; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java index a8d6932acb..11a3855fd6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java @@ -1,41 +1,41 @@ -/* - * 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 - * - * http://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.scp; - -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.messages.SerializableMessage; - -/** - * An interface that is applied to a message when it wants to be told what - * connection it is being sent down prior to it being sent. This is intended to - * allow information about the connection to be used in producing the parsed - * response object. - * - * @author Donal Fellows - */ -public interface ConnectionAwareMessage extends SerializableMessage { - /** - * Tell the object what connection it is being sent on. This will usually - * (except during testing) be called prior to issuing the sequence number, - * but the information provided should not be used until the response is - * being parsed. - * - * @param connection - * The connection. Should not be modified by this - * method. - */ - void setConnection(SCPConnection connection); -} +/* + * 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 + * + * http://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.scp; + +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.messages.SerializableMessage; + +/** + * An interface that is applied to a message when it wants to be told what + * connection it is being sent down prior to it being sent. This is intended to + * allow information about the connection to be used in producing the parsed + * response object. + * + * @author Donal Fellows + */ +public interface ConnectionAwareMessage extends SerializableMessage { + /** + * Tell the object what connection it is being sent on. This will usually + * (except during testing) be called prior to issuing the sequence number, + * but the information provided should not be used until the response is + * being parsed. + * + * @param connection + * The connection. Should not be modified by this + * method. + */ + void setConnection(SCPConnection connection); +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java index 13c9fa7849..e5babaccd2 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2018-2019 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 - * - * http://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.scp; - -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; - -/** - * An SCP response to a request which has an empty payload. - */ -public class EmptyResponse extends CheckOKResponse { - /** - * Create an instance. - * - * @param operation - * The overall operation that we are doing. - * @param command - * The command that we are handling a response to. - * @param buffer - * The buffer holding the response data. - * @throws UnexpectedResponseCodeException - * If the response wasn't OK. - */ - EmptyResponse(String operation, Enum command, ByteBuffer buffer) - throws UnexpectedResponseCodeException { - super(operation, command, buffer); - } -} +/* + * Copyright (c) 2018-2019 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 + * + * http://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.scp; + +import java.nio.ByteBuffer; + +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; + +/** + * An SCP response to a request which has an empty payload. + */ +public class EmptyResponse extends CheckOKResponse { + /** + * Create an instance. + * + * @param operation + * The overall operation that we are doing. + * @param command + * The command that we are handling a response to. + * @param buffer + * The buffer holding the response data. + * @throws UnexpectedResponseCodeException + * If the response wasn't OK. + */ + EmptyResponse(String operation, Enum command, ByteBuffer buffer) + throws UnexpectedResponseCodeException { + super(operation, command, buffer); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java index 1ae9add233..b7e80402e3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java @@ -1,85 +1,85 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -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 uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to a core using FrontEndCommon lib's simulation management - * subsystem. - * - * @param - * The type of response expected. - */ -// TODO Seal in 17 -public abstract class FECRequest extends SCPRequest { - /** - * @param core - * Where to send the request. - * @param replyExpected - * Whether we expect a reply. - * @param command - * What command we are invoking. - */ - FECRequest(HasCoreLocation core, boolean replyExpected, - RunningCommand command) { - super(header(core, replyExpected), command, 0, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param replyExpected - * Whether we expect a reply. - * @param command - * What command we are invoking. - * @param arg1 - * Argument 1. - * @param arg2 - * Argument 2. - * @param arg3 - * Argument 3. - * @param arg4 - * Argument 4. - */ - FECRequest(HasCoreLocation core, boolean replyExpected, - RunningCommand command, int arg1, int arg2, int arg3, int arg4) { - super(header(core, replyExpected), command, arg1, arg2, arg3, - wordAsBuffer(arg4)); - } - - /** - * Make a variant of SDP header that is used to talk to running cores. - * - * @param core - * The SpiNNaker core that we want to talk to. - * @param replyExpected - * Whether we expect a reply. - * @return The SDP header. - */ - private static SDPHeader header(HasCoreLocation core, - boolean replyExpected) { - return new SDPHeader( - replyExpected ? REPLY_EXPECTED : REPLY_NOT_EXPECTED, core, - RUNNING_COMMAND_SDP_PORT); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +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 uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to a core using FrontEndCommon lib's simulation management + * subsystem. + * + * @param + * The type of response expected. + */ +// TODO Seal in 17 +public abstract class FECRequest extends SCPRequest { + /** + * @param core + * Where to send the request. + * @param replyExpected + * Whether we expect a reply. + * @param command + * What command we are invoking. + */ + FECRequest(HasCoreLocation core, boolean replyExpected, + RunningCommand command) { + super(header(core, replyExpected), command, 0, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param replyExpected + * Whether we expect a reply. + * @param command + * What command we are invoking. + * @param arg1 + * Argument 1. + * @param arg2 + * Argument 2. + * @param arg3 + * Argument 3. + * @param arg4 + * Argument 4. + */ + FECRequest(HasCoreLocation core, boolean replyExpected, + RunningCommand command, int arg1, int arg2, int arg3, int arg4) { + super(header(core, replyExpected), command, arg1, arg2, arg3, + wordAsBuffer(arg4)); + } + + /** + * Make a variant of SDP header that is used to talk to running cores. + * + * @param core + * The SpiNNaker core that we want to talk to. + * @param replyExpected + * Whether we expect a reply. + * @return The SDP header. + */ + private static SDPHeader header(HasCoreLocation core, + boolean replyExpected) { + return new SDPHeader( + replyExpected ? REPLY_EXPECTED : REPLY_NOT_EXPECTED, core, + RUNNING_COMMAND_SDP_PORT); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java index 1d85bdeebb..a2057d2073 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java @@ -1,41 +1,41 @@ -/* - * 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 - * - * http://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.scp; - -/** - * Various constants used in the flood fill sub-protocol. - * - * @author Donal Fellows - */ -abstract class FloodFillConstants { - private FloodFillConstants() { - } - - /** Send on all links. */ - static final int FORWARD_LINKS = 0x3F; - - /** Inter-send delay 24μs. */ - static final int DELAY = 0x18; - - /** Number of times to resend a data message. */ - static final int DATA_RESEND = 2; - - /** Initial level. (What is level?) */ - static final int INIT_LEVEL = 3; - - /** Whether to issue an ID for the fill. */ - static final int ADD_ID = 1; -} +/* + * 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 + * + * http://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.scp; + +/** + * Various constants used in the flood fill sub-protocol. + * + * @author Donal Fellows + */ +abstract class FloodFillConstants { + private FloodFillConstants() { + } + + /** Send on all links. */ + static final int FORWARD_LINKS = 0x3F; + + /** Inter-send delay 24μs. */ + static final int DELAY = 0x18; + + /** Number of times to resend a data message. */ + static final int DATA_RESEND = 2; + + /** Initial level. (What is level?) */ + static final int INIT_LEVEL = 3; + + /** Whether to issue an ID for the fill. */ + static final int ADD_ID = 1; +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java index 3280813a1e..74b99fe416 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java @@ -1,61 +1,61 @@ -/* - * 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 - * - * http://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.scp; - -import java.nio.ByteBuffer; -import java.util.function.Supplier; - -import com.google.errorprone.annotations.ForOverride; - -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; - -/** - * A response that holds a payload. - * - * @author Donal Fellows - * @param - * The type of parsed payload value. - * @param - * The type of exception thrown by the payload parser. - */ -public abstract class PayloadedResponse - extends CheckOKResponse implements Supplier { - private final T value; - - PayloadedResponse(String operation, Enum command, ByteBuffer buffer) - throws UnexpectedResponseCodeException, E { - super(operation, command, buffer); - value = parse(buffer); - } - - @Override - public final T get() { - return value; - } - - /** - * Parse the payload of a response. The buffer will be positioned after the - * checked header. - * - * @param buffer - * The buffer to parse. Little-endian. - * @return The parsed value. - * @throws E - * If parsing fails. - */ - @ForOverride - protected abstract T parse(ByteBuffer buffer) throws E; -} +/* + * 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 + * + * http://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.scp; + +import java.nio.ByteBuffer; +import java.util.function.Supplier; + +import com.google.errorprone.annotations.ForOverride; + +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; + +/** + * A response that holds a payload. + * + * @author Donal Fellows + * @param + * The type of parsed payload value. + * @param + * The type of exception thrown by the payload parser. + */ +public abstract class PayloadedResponse + extends CheckOKResponse implements Supplier { + private final T value; + + PayloadedResponse(String operation, Enum command, ByteBuffer buffer) + throws UnexpectedResponseCodeException, E { + super(operation, command, buffer); + value = parse(buffer); + } + + @Override + public final T get() { + return value; + } + + /** + * Parse the payload of a response. The buffer will be positioned after the + * checked header. + * + * @param buffer + * The buffer to parse. Little-endian. + * @return The parsed value. + * @throws E + * If parsing fails. + */ + @ForOverride + protected abstract T parse(ByteBuffer buffer) throws E; +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java index 83ce71e41c..e3755f8362 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java @@ -1,92 +1,92 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_REINJECTION; - -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to an extra monitor control core to manipulate the packet - * reinjection subsystem. - * - * @param - * The type of response. - */ -//TODO Seal in 17 -public abstract class ReinjectorRequest - extends SCPRequest { - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command) { - super(header(core), command, 0, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - * @param argument - * What argument to provide (encoded as an integer). - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, - int argument) { - super(header(core), command, argument, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - * @param argument1 - * The first argument. - * @param argument2 - * The second argument. - * @param argument3 - * The third argument. - * @param body - * Subsequent binary data. - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, - int argument1, int argument2, int argument3, ByteBuffer body) { - super(header(core), command, argument1, argument2, argument3, body); - } - - /** - * Make a variant of SDP header that talks to the packet reinjector. It - * always wants a reply and always talks to a particular SDP port - * (the port for the reinjector). - * - * @param core - * The SpiNNaker core that we want to talk to. Should be running - * the extra monitor core (not checked). - * @return The SDP header. - */ - private static SDPHeader header(HasCoreLocation core) { - return new SDPHeader(REPLY_EXPECTED, core, - EXTRA_MONITOR_CORE_REINJECTION); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_REINJECTION; + +import java.nio.ByteBuffer; + +import uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to an extra monitor control core to manipulate the packet + * reinjection subsystem. + * + * @param + * The type of response. + */ +//TODO Seal in 17 +public abstract class ReinjectorRequest + extends SCPRequest { + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command) { + super(header(core), command, 0, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + * @param argument + * What argument to provide (encoded as an integer). + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, + int argument) { + super(header(core), command, argument, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + * @param argument1 + * The first argument. + * @param argument2 + * The second argument. + * @param argument3 + * The third argument. + * @param body + * Subsequent binary data. + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, + int argument1, int argument2, int argument3, ByteBuffer body) { + super(header(core), command, argument1, argument2, argument3, body); + } + + /** + * Make a variant of SDP header that talks to the packet reinjector. It + * always wants a reply and always talks to a particular SDP port + * (the port for the reinjector). + * + * @param core + * The SpiNNaker core that we want to talk to. Should be running + * the extra monitor core (not checked). + * @return The SDP header. + */ + private static SDPHeader header(HasCoreLocation core) { + return new SDPHeader(REPLY_EXPECTED, core, + EXTRA_MONITOR_CORE_REINJECTION); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java index efc7c26df6..7568635f1b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; - -import java.nio.ByteBuffer; - -import com.google.errorprone.annotations.ForOverride; - -import uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to an extra monitor control core to manipulate the router - * table. - */ -//TODO Seal in 17 -public abstract class RouterTableRequest extends SCPRequest { - private final RouterTableCommand cmd; - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - */ - RouterTableRequest(HasCoreLocation core, RouterTableCommand command) { - super(header(core), command, 0, 0, 0, NO_DATA); - cmd = command; - } - - /** - * Describe the requested operation. - * - * @return A human-readable description of the operation, for failure - * reporting. - */ - @ForOverride - abstract String describe(); - - @Override - public final EmptyResponse getSCPResponse(ByteBuffer buffer) - throws UnexpectedResponseCodeException { - return new EmptyResponse(describe(), cmd, buffer); - } - - /** - * Make a variant of SDP that talks to the packet reinjector for doing - * saving and loading of multicast router tables. - * - * @param core - * The SpiNNaker core that we want to talk to. Should be running - * the extra monitor core. - * @return The SDP header. - */ - static final SDPHeader header(HasCoreLocation core) { - return new SDPHeader(REPLY_EXPECTED, core, GATHERER_DATA_SPEED_UP); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; + +import java.nio.ByteBuffer; + +import com.google.errorprone.annotations.ForOverride; + +import uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to an extra monitor control core to manipulate the router + * table. + */ +//TODO Seal in 17 +public abstract class RouterTableRequest extends SCPRequest { + private final RouterTableCommand cmd; + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + */ + RouterTableRequest(HasCoreLocation core, RouterTableCommand command) { + super(header(core), command, 0, 0, 0, NO_DATA); + cmd = command; + } + + /** + * Describe the requested operation. + * + * @return A human-readable description of the operation, for failure + * reporting. + */ + @ForOverride + abstract String describe(); + + @Override + public final EmptyResponse getSCPResponse(ByteBuffer buffer) + throws UnexpectedResponseCodeException { + return new EmptyResponse(describe(), cmd, buffer); + } + + /** + * Make a variant of SDP that talks to the packet reinjector for doing + * saving and loading of multicast router tables. + * + * @param core + * The SpiNNaker core that we want to talk to. Should be running + * the extra monitor core. + * @return The SDP header. + */ + static final SDPHeader header(HasCoreLocation core) { + return new SDPHeader(REPLY_EXPECTED, core, GATHERER_DATA_SPEED_UP); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java index 42f3ddb9b9..5dd332f814 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java @@ -1,98 +1,98 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.google.errorprone.annotations.Immutable; - -import uk.ac.manchester.spinnaker.machine.board.ValidTriadX; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadY; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadZ; - -/** - * A combination of x, y, z and a Link. - * - * @author Christian - */ -@JsonPropertyOrder({ - "x", "y", "z", "link" -}) -@JsonFormat(shape = ARRAY) -@Immutable -public class BoardLink { - // TODO verify format and meaning. - - @ValidTriadX - private final int x; - - @ValidTriadY - private final int y; - - @ValidTriadZ - private final int z; - - private final int link; - - /** - * @param x - * The X coordinate - * @param y - * The Y coordinate - * @param z - * The Z coordinate - * @param link - * The link number - */ - public BoardLink(@JsonProperty("x") int x, @JsonProperty("y") int y, - @JsonProperty("z") int z, @JsonProperty("link") int link) { - this.x = x; - this.y = y; - this.z = z; - this.link = link; - } - - /** - * @return the X coordinate - */ - public int getX() { - return x; - } - - /** - * @return the Y coordinate - */ - public int getY() { - return y; - } - - /** - * @return the Z coordinate - */ - public int getZ() { - return z; - } - - /** - * @return the link number - */ - public int getLink() { - return link; - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.google.errorprone.annotations.Immutable; + +import uk.ac.manchester.spinnaker.machine.board.ValidTriadX; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadY; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadZ; + +/** + * A combination of x, y, z and a Link. + * + * @author Christian + */ +@JsonPropertyOrder({ + "x", "y", "z", "link" +}) +@JsonFormat(shape = ARRAY) +@Immutable +public class BoardLink { + // TODO verify format and meaning. + + @ValidTriadX + private final int x; + + @ValidTriadY + private final int y; + + @ValidTriadZ + private final int z; + + private final int link; + + /** + * @param x + * The X coordinate + * @param y + * The Y coordinate + * @param z + * The Z coordinate + * @param link + * The link number + */ + public BoardLink(@JsonProperty("x") int x, @JsonProperty("y") int y, + @JsonProperty("z") int z, @JsonProperty("link") int link) { + this.x = x; + this.y = y; + this.z = z; + this.link = link; + } + + /** + * @return the X coordinate + */ + public int getX() { + return x; + } + + /** + * @return the Y coordinate + */ + public int getY() { + return y; + } + + /** + * @return the Z coordinate + */ + public int getZ() { + return z; + } + + /** + * @return the link number + */ + public int getLink() { + return link; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java index ad6b9904e8..5d1238f28f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java @@ -1,109 +1,109 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.transceiver; - -import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_OFFSET; -import static uk.ac.manchester.spinnaker.messages.Constants.ROUTER_REGISTER_P2P_ADDRESS; -import static uk.ac.manchester.spinnaker.messages.Constants.SYSTEM_VARIABLE_BASE_ADDRESS; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; - -/** - * Common memory locations. Note that many locations really come in both - * buffered and unbuffered varieties, but this class doesn't hold all standard - * locations and versions: - *

Buffered SDRAM means that writes go through a write buffer. - * Unbuffered means that they go directly to SDRAM. Reads are unaffected in - * general. If you are writing lots of data, it is unlikely to matter much since - * the write buffer is limited in size. Here you probably want to use Unbuffered - * anyway, as it will then block until the write is definitely done. Using - * Buffered writing means that the write may or may not have happened at the - * time of the response.
- * - * @author Donal Fellows - */ -public abstract class CommonMemoryLocations { - private CommonMemoryLocations() { - } - - /** - * Start of unbuffered access to SDRAM. Writes will block until they have - * completed. - */ - public static final MemoryLocation UNBUFFERED_SDRAM_START = - new MemoryLocation(0x60000000); - - /** Location of routing table data in transit. Reserved by SCAMP. */ - public static final MemoryLocation ROUTING_TABLE_DATA = - new MemoryLocation(0x67800000); - - /** - * Where executables are written to prior to launching them. Reserved by - * SCAMP. - */ - public static final MemoryLocation EXECUTABLE_ADDRESS = - new MemoryLocation(0x67800000); - - /** - * Start of buffered access to SDRAM. Writes will finish rapidly, but data - * may take some cycles to appear in memory. - *

- * It doesn't matter too much when working from host; the time to do the - * network communications is rather longer than the normal buffering time - * for SDRAM. - */ - public static final MemoryLocation BUFFERED_SDRAM_START = - new MemoryLocation(0x70000000); - - /** Location of the bank of memory-mapped router registers. Buffered. */ - public static final MemoryLocation ROUTER_BASE = - new MemoryLocation(0xe1000000); - - /** Location of the memory-mapped router control register (r0). */ - public static final MemoryLocation ROUTER_CONTROL = - new MemoryLocation(0xe1000000); - - /** Location of the memory-mapped router error register (r5). */ - public static final MemoryLocation ROUTER_ERROR = - new MemoryLocation(0xe1000014); - - /** - * Where to write router diagnostic counters control data to (r11). - * Unbuffered. - */ - public static final MemoryLocation ROUTER_DIAGNOSTIC_COUNTER = - new MemoryLocation(0xf100002c); - - /** Location of the memory-mapped router filtering registers (rFN). */ - public static final MemoryLocation ROUTER_FILTERS = - new MemoryLocation(0xe1000200); - - /** Location of the memory-mapped router diagnostics registers (rCN). */ - public static final MemoryLocation ROUTER_DIAGNOSTICS = - new MemoryLocation(0xe1000300); - - /** The base address of a router's P2P routing table, 3 bits per route. */ - public static final MemoryLocation ROUTER_P2P = - new MemoryLocation(ROUTER_REGISTER_P2P_ADDRESS); - - /** Where the CPU information structure is located. Buffered system RAM. */ - public static final MemoryLocation CPU_INFO = - new MemoryLocation(CPU_INFO_OFFSET); - - /** Where the system variables are located. Unbuffered system RAM. */ - public static final MemoryLocation SYS_VARS = - new MemoryLocation(SYSTEM_VARIABLE_BASE_ADDRESS); -} +/* + * Copyright (c) 2022 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 + * + * http://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.transceiver; + +import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_OFFSET; +import static uk.ac.manchester.spinnaker.messages.Constants.ROUTER_REGISTER_P2P_ADDRESS; +import static uk.ac.manchester.spinnaker.messages.Constants.SYSTEM_VARIABLE_BASE_ADDRESS; + +import uk.ac.manchester.spinnaker.machine.MemoryLocation; + +/** + * Common memory locations. Note that many locations really come in both + * buffered and unbuffered varieties, but this class doesn't hold all standard + * locations and versions: + *

Buffered SDRAM means that writes go through a write buffer. + * Unbuffered means that they go directly to SDRAM. Reads are unaffected in + * general. If you are writing lots of data, it is unlikely to matter much since + * the write buffer is limited in size. Here you probably want to use Unbuffered + * anyway, as it will then block until the write is definitely done. Using + * Buffered writing means that the write may or may not have happened at the + * time of the response.
+ * + * @author Donal Fellows + */ +public abstract class CommonMemoryLocations { + private CommonMemoryLocations() { + } + + /** + * Start of unbuffered access to SDRAM. Writes will block until they have + * completed. + */ + public static final MemoryLocation UNBUFFERED_SDRAM_START = + new MemoryLocation(0x60000000); + + /** Location of routing table data in transit. Reserved by SCAMP. */ + public static final MemoryLocation ROUTING_TABLE_DATA = + new MemoryLocation(0x67800000); + + /** + * Where executables are written to prior to launching them. Reserved by + * SCAMP. + */ + public static final MemoryLocation EXECUTABLE_ADDRESS = + new MemoryLocation(0x67800000); + + /** + * Start of buffered access to SDRAM. Writes will finish rapidly, but data + * may take some cycles to appear in memory. + *

+ * It doesn't matter too much when working from host; the time to do the + * network communications is rather longer than the normal buffering time + * for SDRAM. + */ + public static final MemoryLocation BUFFERED_SDRAM_START = + new MemoryLocation(0x70000000); + + /** Location of the bank of memory-mapped router registers. Buffered. */ + public static final MemoryLocation ROUTER_BASE = + new MemoryLocation(0xe1000000); + + /** Location of the memory-mapped router control register (r0). */ + public static final MemoryLocation ROUTER_CONTROL = + new MemoryLocation(0xe1000000); + + /** Location of the memory-mapped router error register (r5). */ + public static final MemoryLocation ROUTER_ERROR = + new MemoryLocation(0xe1000014); + + /** + * Where to write router diagnostic counters control data to (r11). + * Unbuffered. + */ + public static final MemoryLocation ROUTER_DIAGNOSTIC_COUNTER = + new MemoryLocation(0xf100002c); + + /** Location of the memory-mapped router filtering registers (rFN). */ + public static final MemoryLocation ROUTER_FILTERS = + new MemoryLocation(0xe1000200); + + /** Location of the memory-mapped router diagnostics registers (rCN). */ + public static final MemoryLocation ROUTER_DIAGNOSTICS = + new MemoryLocation(0xe1000300); + + /** The base address of a router's P2P routing table, 3 bits per route. */ + public static final MemoryLocation ROUTER_P2P = + new MemoryLocation(ROUTER_REGISTER_P2P_ADDRESS); + + /** Where the CPU information structure is located. Buffered system RAM. */ + public static final MemoryLocation CPU_INFO = + new MemoryLocation(CPU_INFO_OFFSET); + + /** Where the system variables are located. Unbuffered system RAM. */ + public static final MemoryLocation SYS_VARS = + new MemoryLocation(SYSTEM_VARIABLE_BASE_ADDRESS); +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java index 856cd0ba52..595f62219e 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java @@ -1,58 +1,58 @@ -/* - * 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 - * - * http://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.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - -/** - * - * @author micro - */ -public class TestVersion { - - @Test - public void testThreeUnquoted() { - var version = new Version("1.2.3"); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(3, version.revision); - } - - @Test - public void testThreeQuoted() { - var version = new Version("\"1.2.3\""); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(3, version.revision); - } - - @Test - public void testTwoUnquoted() { - var version = new Version("1.2"); - assertEquals(1, version.majorVersion); - assertEquals(2, version.minorVersion); - assertEquals(0, version.revision); - } - - @Test - public void testOneQuoted() { - var version = new Version("\"1\""); - assertEquals(1, version.majorVersion); - assertEquals(0, version.minorVersion); - assertEquals(0, version.revision); - } -} +/* + * 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 + * + * http://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.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * + * @author micro + */ +public class TestVersion { + + @Test + public void testThreeUnquoted() { + var version = new Version("1.2.3"); + assertEquals(1, version.majorVersion); + assertEquals(2, version.minorVersion); + assertEquals(3, version.revision); + } + + @Test + public void testThreeQuoted() { + var version = new Version("\"1.2.3\""); + assertEquals(1, version.majorVersion); + assertEquals(2, version.minorVersion); + assertEquals(3, version.revision); + } + + @Test + public void testTwoUnquoted() { + var version = new Version("1.2"); + assertEquals(1, version.majorVersion); + assertEquals(2, version.minorVersion); + assertEquals(0, version.revision); + } + + @Test + public void testOneQuoted() { + var version = new Version("\"1\""); + assertEquals(1, version.majorVersion); + assertEquals(0, version.minorVersion); + assertEquals(0, version.revision); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java index 2be188e205..2b5a057475 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java @@ -1,47 +1,47 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestBoardCoordinates { - - @Test - void testFromJson() throws IOException { - var json = "[2, 4, 6]"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, BoardCoordinates.class); - assertEquals(2, fromJson.getX()); - assertEquals(4, fromJson.getY()); - assertEquals(6, fromJson.getZ()); - - var direct = new BoardCoordinates(2, 4, 6); - assertEquals(direct, fromJson); - assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestBoardCoordinates { + + @Test + void testFromJson() throws IOException { + var json = "[2, 4, 6]"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, BoardCoordinates.class); + assertEquals(2, fromJson.getX()); + assertEquals(4, fromJson.getY()); + assertEquals(6, fromJson.getZ()); + + var direct = new BoardCoordinates(2, 4, 6); + assertEquals(direct, fromJson); + assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java index 30864cdfe5..7b7835e4b3 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java @@ -1,47 +1,47 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestBoardPhysicalCoordinates { - - @Test - void testFromJson() throws IOException { - var json = "[2, 4, 6]"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, BoardPhysicalCoordinates.class); - assertEquals(2, fromJson.getCabinet()); - assertEquals(4, fromJson.getFrame()); - assertEquals(6, fromJson.getBoard()); - - var direct = new BoardPhysicalCoordinates(2, 4, 6); - assertEquals(direct, fromJson); - assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestBoardPhysicalCoordinates { + + @Test + void testFromJson() throws IOException { + var json = "[2, 4, 6]"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, BoardPhysicalCoordinates.class); + assertEquals(2, fromJson.getCabinet()); + assertEquals(4, fromJson.getFrame()); + assertEquals(6, fromJson.getBoard()); + + var direct = new BoardPhysicalCoordinates(2, 4, 6); + assertEquals(direct, fromJson); + assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java index c7bc6aae7b..d8395c047a 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java @@ -1,86 +1,86 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.hamcrest.collection.IsMapContaining; -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestJobDescription { - @Test - void testOneArg() throws IOException { - var json = "{\"job_id\":12345," - + "\"owner\":\"someone@manchester.ac.uk\"," - + "\"start_time\":1.537284307847865E9," - + "\"keepalive\":45.0," - + "\"state\":3," - + "\"power\":true," - + "\"args\":[1]," - + "\"kwargs\":{" + ( - "\"tags\":null," - + "\"max_dead_boards\":0," - + "\"machine\":null," - + "\"min_ratio\":0.333," - + "\"max_dead_links\":null," - + "\"require_torus\":false" - ) + "}," - + "\"allocated_machine_name\":\"Spin24b-223\"," - + "\"boards\":[[1,1,2]]," - + "\"keepalivehost\":\"130.88.198.171\"}"; - - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobDescription.class); - assertEquals(12345, fromJson.getJobID()); - assertEquals("someone@manchester.ac.uk", fromJson.getOwner()); - assertEquals(1.537284307847865E9, fromJson.getStartTime()); - assertEquals(45, fromJson.getKeepAlive()); - assertEquals(State.values()[3], fromJson.getState()); - assertEquals(true, fromJson.getPower()); - assertThat(fromJson.getArgs(), contains(1)); - var map = fromJson.getKwargs(); - assertThat(map, IsMapContaining.hasEntry("tags", null)); - assertThat(map, IsMapContaining.hasEntry("max_dead_boards", 0)); - assertThat(map, IsMapContaining.hasEntry("machine", null)); - assertThat(map, IsMapContaining.hasEntry("min_ratio", 0.333)); - assertThat(map, IsMapContaining.hasEntry("max_dead_links", null)); - assertThat(map, IsMapContaining.hasEntry("require_torus", false)); - assertEquals("Spin24b-223", fromJson.getMachine()); - assertThat(fromJson.getBoards(), - contains(new BoardCoordinates(1, 1, 2))); - assertEquals("130.88.198.171", fromJson.getKeepAliveHost()); - } - - @Test - void testNulls() throws IOException { - var json = "{\"job_id\":null}"; - - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobDescription.class); - assertEquals(0, fromJson.getJobID()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.hamcrest.collection.IsMapContaining; +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestJobDescription { + @Test + void testOneArg() throws IOException { + var json = "{\"job_id\":12345," + + "\"owner\":\"someone@manchester.ac.uk\"," + + "\"start_time\":1.537284307847865E9," + + "\"keepalive\":45.0," + + "\"state\":3," + + "\"power\":true," + + "\"args\":[1]," + + "\"kwargs\":{" + ( + "\"tags\":null," + + "\"max_dead_boards\":0," + + "\"machine\":null," + + "\"min_ratio\":0.333," + + "\"max_dead_links\":null," + + "\"require_torus\":false" + ) + "}," + + "\"allocated_machine_name\":\"Spin24b-223\"," + + "\"boards\":[[1,1,2]]," + + "\"keepalivehost\":\"130.88.198.171\"}"; + + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobDescription.class); + assertEquals(12345, fromJson.getJobID()); + assertEquals("someone@manchester.ac.uk", fromJson.getOwner()); + assertEquals(1.537284307847865E9, fromJson.getStartTime()); + assertEquals(45, fromJson.getKeepAlive()); + assertEquals(State.values()[3], fromJson.getState()); + assertEquals(true, fromJson.getPower()); + assertThat(fromJson.getArgs(), contains(1)); + var map = fromJson.getKwargs(); + assertThat(map, IsMapContaining.hasEntry("tags", null)); + assertThat(map, IsMapContaining.hasEntry("max_dead_boards", 0)); + assertThat(map, IsMapContaining.hasEntry("machine", null)); + assertThat(map, IsMapContaining.hasEntry("min_ratio", 0.333)); + assertThat(map, IsMapContaining.hasEntry("max_dead_links", null)); + assertThat(map, IsMapContaining.hasEntry("require_torus", false)); + assertEquals("Spin24b-223", fromJson.getMachine()); + assertThat(fromJson.getBoards(), + contains(new BoardCoordinates(1, 1, 2))); + assertEquals("130.88.198.171", fromJson.getKeepAliveHost()); + } + + @Test + void testNulls() throws IOException { + var json = "{\"job_id\":null}"; + + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobDescription.class); + assertEquals(0, fromJson.getJobID()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java index e3fefe341a..545c08ca12 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java @@ -1,66 +1,66 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -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 java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestJobMachineInfo { - @Test - void testFromJson() throws IOException { - var json = "{\"connections\":[[[0,0],\"10.2.225.177\"]," - + "[[4,8],\"10.2.225.145\"],[[0,12],\"10.2.225.185\"]," - + "[[8,16],\"10.2.225.121\"],[[4,20],\"10.2.225.153\"]," - + "[[8,4],\"10.2.225.113\"]]," - + "\"width\":16,\"machine_name\":\"Spin24b-001\"," - + "\"boards\":" - + "[[2,1,1],[2,1,0],[2,1,2],[2,0,2],[2,0,1],[2,0,0]]," - + "\"height\":24}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobMachineInfo.class); - assertEquals(6, fromJson.getConnections().size()); - assertEquals(6, fromJson.getBoards().size()); - assertEquals(16, fromJson.getWidth()); - assertEquals(24, fromJson.getHeight()); - assertEquals("Spin24b-001", fromJson.getMachineName()); - } - - @Test - void testNullJson() throws IOException { - var json = "{\"connections\":null," - + "\"machine_name\":null," - + "\"boards\":null}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobMachineInfo.class); - assertEquals(0, fromJson.getConnections().size()); - assertEquals(0, fromJson.getBoards().size()); - assertEquals(0, fromJson.getWidth()); - assertEquals(0, fromJson.getHeight()); - assertNull(fromJson.getMachineName()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +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 java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestJobMachineInfo { + @Test + void testFromJson() throws IOException { + var json = "{\"connections\":[[[0,0],\"10.2.225.177\"]," + + "[[4,8],\"10.2.225.145\"],[[0,12],\"10.2.225.185\"]," + + "[[8,16],\"10.2.225.121\"],[[4,20],\"10.2.225.153\"]," + + "[[8,4],\"10.2.225.113\"]]," + + "\"width\":16,\"machine_name\":\"Spin24b-001\"," + + "\"boards\":" + + "[[2,1,1],[2,1,0],[2,1,2],[2,0,2],[2,0,1],[2,0,0]]," + + "\"height\":24}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobMachineInfo.class); + assertEquals(6, fromJson.getConnections().size()); + assertEquals(6, fromJson.getBoards().size()); + assertEquals(16, fromJson.getWidth()); + assertEquals(24, fromJson.getHeight()); + assertEquals("Spin24b-001", fromJson.getMachineName()); + } + + @Test + void testNullJson() throws IOException { + var json = "{\"connections\":null," + + "\"machine_name\":null," + + "\"boards\":null}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobMachineInfo.class); + assertEquals(0, fromJson.getConnections().size()); + assertEquals(0, fromJson.getBoards().size()); + assertEquals(0, fromJson.getWidth()); + assertEquals(0, fromJson.getHeight()); + assertNull(fromJson.getMachineName()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java index 1edb5a8eb3..ceb76fa6c8 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java @@ -1,90 +1,90 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestMachine { - - @Test - void testFromJson() throws IOException { - var json = "{\"name\":\"power-monitor\"," - + "\"tags\":[\"power-monitor\",\"machine-room\"]," - + "\"width\":1,\"height\":1," - + "\"dead_boards\":[[0,0,1],[0,0,2]],\"dead_links\":[]}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertEquals("power-monitor", fromJson.getName()); - assertThat(fromJson.getTags(), - contains("power-monitor", "machine-room")); - assertEquals(1, fromJson.getWidth()); - assertEquals(1, fromJson.getHeight()); - assertThat(fromJson.getDeadBoards(), contains( - new BoardCoordinates(0, 0, 1), new BoardCoordinates(0, 0, 2))); - assertEquals(0, fromJson.getDeadLinks().size()); - assertNotNull(fromJson.toString()); - } - - @Test - void testAssumedDeadLinks() throws IOException { - var json = "{\"name\":\"power-monitor\"," - + "\"tags\":[\"power-monitor\",\"machine-room\"]," - + "\"width\":1,\"height\":1," - + "\"dead_boards\":[[1,2,3],[4,5,6]]," - + "\"dead_links\":[[7,8,9,10],[11,12,13,14]]}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertEquals("power-monitor", fromJson.getName()); - assertThat(fromJson.getTags(), - contains("power-monitor", "machine-room")); - assertEquals(1, fromJson.getWidth()); - assertEquals(1, fromJson.getHeight()); - assertThat(fromJson.getDeadBoards(), contains( - new BoardCoordinates(1, 2, 3), new BoardCoordinates(4, 5, 6))); - assertEquals(2, fromJson.getDeadLinks().size()); - assertEquals(7, fromJson.getDeadLinks().get(0).getX()); - assertEquals(14, fromJson.getDeadLinks().get(1).getLink()); - assertNotNull(fromJson.toString()); - } - - @Test - void testNullJson() throws IOException { - var json = "{\"name\":null}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertNull(fromJson.getName()); - assertTrue(fromJson.getTags().isEmpty(), "must have no tags"); - assertEquals(0, fromJson.getWidth()); - assertEquals(0, fromJson.getHeight()); - assertTrue(fromJson.getDeadBoards().isEmpty(), - "must have no dead boards"); - assertTrue(fromJson.getDeadLinks().isEmpty(), - "must have no dead links"); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestMachine { + + @Test + void testFromJson() throws IOException { + var json = "{\"name\":\"power-monitor\"," + + "\"tags\":[\"power-monitor\",\"machine-room\"]," + + "\"width\":1,\"height\":1," + + "\"dead_boards\":[[0,0,1],[0,0,2]],\"dead_links\":[]}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertEquals("power-monitor", fromJson.getName()); + assertThat(fromJson.getTags(), + contains("power-monitor", "machine-room")); + assertEquals(1, fromJson.getWidth()); + assertEquals(1, fromJson.getHeight()); + assertThat(fromJson.getDeadBoards(), contains( + new BoardCoordinates(0, 0, 1), new BoardCoordinates(0, 0, 2))); + assertEquals(0, fromJson.getDeadLinks().size()); + assertNotNull(fromJson.toString()); + } + + @Test + void testAssumedDeadLinks() throws IOException { + var json = "{\"name\":\"power-monitor\"," + + "\"tags\":[\"power-monitor\",\"machine-room\"]," + + "\"width\":1,\"height\":1," + + "\"dead_boards\":[[1,2,3],[4,5,6]]," + + "\"dead_links\":[[7,8,9,10],[11,12,13,14]]}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertEquals("power-monitor", fromJson.getName()); + assertThat(fromJson.getTags(), + contains("power-monitor", "machine-room")); + assertEquals(1, fromJson.getWidth()); + assertEquals(1, fromJson.getHeight()); + assertThat(fromJson.getDeadBoards(), contains( + new BoardCoordinates(1, 2, 3), new BoardCoordinates(4, 5, 6))); + assertEquals(2, fromJson.getDeadLinks().size()); + assertEquals(7, fromJson.getDeadLinks().get(0).getX()); + assertEquals(14, fromJson.getDeadLinks().get(1).getLink()); + assertNotNull(fromJson.toString()); + } + + @Test + void testNullJson() throws IOException { + var json = "{\"name\":null}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertNull(fromJson.getName()); + assertTrue(fromJson.getTags().isEmpty(), "must have no tags"); + assertEquals(0, fromJson.getWidth()); + assertEquals(0, fromJson.getHeight()); + assertTrue(fromJson.getDeadBoards().isEmpty(), + "must have no dead boards"); + assertTrue(fromJson.getDeadLinks().isEmpty(), + "must have no dead links"); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java index 0ed00a205a..77794af72c 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java @@ -1,63 +1,63 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestState { - - @Test - void testFromJson() throws IOException { - var json = "{\"state\":2," - + "\"power\":true," - + "\"keepalive\":60.0," - + "\"reason\":null," - + "\"start_time\":1.125," - + "\"keepalivehost\":\"86.82.216.229\"}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobState.class); - assertEquals(State.POWER, fromJson.getState()); - assertEquals(true, fromJson.getPower()); - assertEquals(1.125, fromJson.getStartTime()); - assertEquals(60, fromJson.getKeepalive()); - assertNull(fromJson.getReason()); - assertEquals("86.82.216.229", fromJson.getKeepalivehost()); - assertNotNull(fromJson.toString()); - } - - @Test - void testNullJson() throws IOException { - var json = "{\"reason\":null}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobState.class); - assertNull(fromJson.getState()); - assertNull(fromJson.getPower()); - assertNull(fromJson.getReason()); - assertEquals(0.0, fromJson.getStartTime()); - assertNull(fromJson.getKeepalivehost()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestState { + + @Test + void testFromJson() throws IOException { + var json = "{\"state\":2," + + "\"power\":true," + + "\"keepalive\":60.0," + + "\"reason\":null," + + "\"start_time\":1.125," + + "\"keepalivehost\":\"86.82.216.229\"}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobState.class); + assertEquals(State.POWER, fromJson.getState()); + assertEquals(true, fromJson.getPower()); + assertEquals(1.125, fromJson.getStartTime()); + assertEquals(60, fromJson.getKeepalive()); + assertNull(fromJson.getReason()); + assertEquals("86.82.216.229", fromJson.getKeepalivehost()); + assertNotNull(fromJson.toString()); + } + + @Test + void testNullJson() throws IOException { + var json = "{\"reason\":null}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobState.class); + assertNull(fromJson.getState()); + assertNull(fromJson.getPower()); + assertNull(fromJson.getReason()); + assertEquals(0.0, fromJson.getStartTime()); + assertNull(fromJson.getKeepalivehost()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java index 168e4bf5e4..97dca1fdef 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java @@ -1,110 +1,110 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author micro - */ -public class TestWhereIs { - - @Test - void testFromJson() throws IOException { - var jobChip = new ChipLocation(1, 2); - var chip = new ChipLocation(3, 4); - var boardChip = new ChipLocation(8, 9); - var logical = new BoardCoordinates(5, 6, 7); - var physical = new BoardPhysicalCoordinates(10, 11, 12); - - var json = "{\"job_chip\":[1,2],\"job_id\":666,\"chip\":[3,4]," - + "\"logical\":[5,6,7],\"machine\":\"Spin24b-001\"," - + "\"board_chip\":[8,9],\"physical\":[10,11,12]}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertEquals(jobChip, fromJson.getJobChip()); - assertEquals(666, fromJson.getJobId()); - assertEquals(chip, fromJson.getChip()); - assertEquals(logical, fromJson.getLogical()); - assertEquals("Spin24b-001", fromJson.getMachine()); - assertEquals(boardChip, fromJson.getBoardChip()); - var physical2 = fromJson.getPhysical(); - assertEquals(physical, physical2); - - var direct = new WhereIs(jobChip, 666, chip, logical, "Spin24b-001", - boardChip, physical); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - - @Test - void testBug() throws IOException { - var chip = new ChipLocation(8, 4); - var boardChip = new ChipLocation(0, 0); - var logical = new BoardCoordinates(0, 0, 1); - var physical = new BoardPhysicalCoordinates(0, 0, 8); - - var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":[8,4]," - + "\"logical\":[0,0,1],\"machine\":\"Spin24b-001\"," - + "\"board_chip\":[0,0],\"physical\":[0,0,8]}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.getJobChip()); - assertNull(fromJson.getJobId()); - assertEquals(chip, fromJson.getChip()); - assertEquals(logical, fromJson.getLogical()); - assertEquals("Spin24b-001", fromJson.getMachine()); - assertEquals(boardChip, fromJson.getBoardChip()); - assertEquals(physical, fromJson.getPhysical()); - - var direct = new WhereIs(null, null, chip, logical, "Spin24b-001", - boardChip, physical); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - - @Test - void testNulls() throws IOException { - - var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":null," - + "\"logical\":null,\"machine\":null,\"board_chip\":null," - + "\"physical\":null}"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.getJobChip()); - assertNull(fromJson.getJobId()); - assertNull(fromJson.getChip()); - assertNull(fromJson.getLogical()); - assertNull(fromJson.getMachine()); - assertNull(fromJson.getBoardChip()); - assertNull(fromJson.getPhysical()); - - var direct = new WhereIs(null, null, null, null, null, null, null); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author micro + */ +public class TestWhereIs { + + @Test + void testFromJson() throws IOException { + var jobChip = new ChipLocation(1, 2); + var chip = new ChipLocation(3, 4); + var boardChip = new ChipLocation(8, 9); + var logical = new BoardCoordinates(5, 6, 7); + var physical = new BoardPhysicalCoordinates(10, 11, 12); + + var json = "{\"job_chip\":[1,2],\"job_id\":666,\"chip\":[3,4]," + + "\"logical\":[5,6,7],\"machine\":\"Spin24b-001\"," + + "\"board_chip\":[8,9],\"physical\":[10,11,12]}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertEquals(jobChip, fromJson.getJobChip()); + assertEquals(666, fromJson.getJobId()); + assertEquals(chip, fromJson.getChip()); + assertEquals(logical, fromJson.getLogical()); + assertEquals("Spin24b-001", fromJson.getMachine()); + assertEquals(boardChip, fromJson.getBoardChip()); + var physical2 = fromJson.getPhysical(); + assertEquals(physical, physical2); + + var direct = new WhereIs(jobChip, 666, chip, logical, "Spin24b-001", + boardChip, physical); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + + @Test + void testBug() throws IOException { + var chip = new ChipLocation(8, 4); + var boardChip = new ChipLocation(0, 0); + var logical = new BoardCoordinates(0, 0, 1); + var physical = new BoardPhysicalCoordinates(0, 0, 8); + + var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":[8,4]," + + "\"logical\":[0,0,1],\"machine\":\"Spin24b-001\"," + + "\"board_chip\":[0,0],\"physical\":[0,0,8]}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertNull(fromJson.getJobChip()); + assertNull(fromJson.getJobId()); + assertEquals(chip, fromJson.getChip()); + assertEquals(logical, fromJson.getLogical()); + assertEquals("Spin24b-001", fromJson.getMachine()); + assertEquals(boardChip, fromJson.getBoardChip()); + assertEquals(physical, fromJson.getPhysical()); + + var direct = new WhereIs(null, null, chip, logical, "Spin24b-001", + boardChip, physical); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + + @Test + void testNulls() throws IOException { + + var json = "{\"job_chip\":null,\"job_id\":null,\"chip\":null," + + "\"logical\":null,\"machine\":null,\"board_chip\":null," + + "\"physical\":null}"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertNull(fromJson.getJobChip()); + assertNull(fromJson.getJobId()); + assertNull(fromJson.getChip()); + assertNull(fromJson.getLogical()); + assertNull(fromJson.getMachine()); + assertNull(fromJson.getBoardChip()); + assertNull(fromJson.getPhysical()); + + var direct = new WhereIs(null, null, null, null, null, null, null); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/resources/spinn2.json b/SpiNNaker-comms/src/test/resources/spinn2.json index 89e2f8bd6d..e2be180d63 100644 --- a/SpiNNaker-comms/src/test/resources/spinn2.json +++ b/SpiNNaker-comms/src/test/resources/spinn2.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-comms/src/test/resources/spinn4.json b/SpiNNaker-comms/src/test/resources/spinn4.json index 91f9918a2c..e72356b586 100644 --- a/SpiNNaker-comms/src/test/resources/spinn4.json +++ b/SpiNNaker-comms/src/test/resources/spinn4.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 18, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 18, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 18, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 18, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 18, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 18, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 18, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 18, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 18, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 18, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist b/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist index 916dee007f..a40276a0f2 100644 --- a/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist +++ b/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist @@ -1,18 +1,18 @@ -# Copyright (c) 2022 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 -# -# http://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. - -chip 1 1 dead -chip 1 0 core 2,3 link 4,5 -# Include some high numbers -chip 7 7 link 1,5 core 10,17 +# Copyright (c) 2022 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 +# +# http://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. + +chip 1 1 dead +chip 1 0 core 2,3 link 4,5 +# Include some high numbers +chip 7 7 link 1,5 core 10,17 diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java index 000125a815..42e2b8ddf4 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java @@ -1,127 +1,127 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.front_end.dse; - -import static uk.ac.manchester.spinnaker.front_end.Constants.PARALLEL_SIZE; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.List; -import java.util.function.Function; - -import com.google.errorprone.annotations.MustBeClosed; - -import uk.ac.manchester.spinnaker.data_spec.DataSpecificationException; -import uk.ac.manchester.spinnaker.front_end.BasicExecutor; -import uk.ac.manchester.spinnaker.front_end.BoardLocalSupport; -import uk.ac.manchester.spinnaker.front_end.BasicExecutor.SimpleCallable; -import uk.ac.manchester.spinnaker.machine.Machine; -import uk.ac.manchester.spinnaker.storage.StorageException; -import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; -import uk.ac.manchester.spinnaker.storage.DSEStorage.Ethernet; -import uk.ac.manchester.spinnaker.transceiver.ProcessException; -import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; - -/** - * Common base for executing data specifications. - * - * @author Donal Fellows - */ -public abstract class ExecuteDataSpecification extends BoardLocalSupport - implements AutoCloseable { - /** The database. */ - protected final DSEDatabaseEngine db; - - /** How to run tasks in parallel. */ - private final BasicExecutor executor; - - /** - * @param txrx - * The transceiver for talking to the SpiNNaker machine. - * @param machine - * The description of the SpiNNaker machine. - * @param db - * The DSE database. - * @throws IOException - * If the transceiver can't talk to its sockets. - * @throws ProcessException - * If SpiNNaker rejects a message. - * @throws InterruptedException - * If communications are interrupted. - * @throws IllegalStateException - * If something really strange occurs with talking to the BMP; - * this constructor should not be doing that! - * @throws StorageException - * If the database cannot be read. - * @throws URISyntaxException - * If the proxy URI is specified but not valid. - */ - @MustBeClosed - @SuppressWarnings("MustBeClosed") - protected ExecuteDataSpecification(TransceiverInterface txrx, - Machine machine, DSEDatabaseEngine db) - throws IOException, ProcessException, InterruptedException, - StorageException, URISyntaxException { - super((db == null) ? null : txrx, machine); - this.db = db; - this.executor = new BasicExecutor(PARALLEL_SIZE); - } - - @Override - public final void close() throws IOException, InterruptedException { - if (txrx != null) { - txrx.close(); - } - executor.close(); - } - - /** - * Run the tasks in parallel. Submits to {@link #executor} and detoxifies - * the exceptions. - * - * @param tasks - * The tasks to run. - * @param mapper - * Gets how to implement a task. - * @throws StorageException - * If the database can't be talked to. - * @throws IOException - * If the transceiver can't talk to its sockets. - * @throws ProcessException - * If SpiNNaker rejects a message. - * @throws DataSpecificationException - * If a data specification in the database is invalid. - * @throws InterruptedException - * If communications are interrupted. - * @throws IllegalStateException - * If an unexpected exception occurs in any of the parallel - * tasks. - */ - protected final void processTasksInParallel(List tasks, - Function mapper) throws StorageException, - IOException, ProcessException, DataSpecificationException, - InterruptedException { - try { - executor.submitTasks(tasks, mapper).awaitAndCombineExceptions(); - } catch (StorageException | IOException | ProcessException - | DataSpecificationException | InterruptedException - | RuntimeException e) { - throw e; - } catch (Exception e) { - throw new IllegalStateException("unexpected exception", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.front_end.dse; + +import static uk.ac.manchester.spinnaker.front_end.Constants.PARALLEL_SIZE; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.List; +import java.util.function.Function; + +import com.google.errorprone.annotations.MustBeClosed; + +import uk.ac.manchester.spinnaker.data_spec.DataSpecificationException; +import uk.ac.manchester.spinnaker.front_end.BasicExecutor; +import uk.ac.manchester.spinnaker.front_end.BoardLocalSupport; +import uk.ac.manchester.spinnaker.front_end.BasicExecutor.SimpleCallable; +import uk.ac.manchester.spinnaker.machine.Machine; +import uk.ac.manchester.spinnaker.storage.StorageException; +import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; +import uk.ac.manchester.spinnaker.storage.DSEStorage.Ethernet; +import uk.ac.manchester.spinnaker.transceiver.ProcessException; +import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; + +/** + * Common base for executing data specifications. + * + * @author Donal Fellows + */ +public abstract class ExecuteDataSpecification extends BoardLocalSupport + implements AutoCloseable { + /** The database. */ + protected final DSEDatabaseEngine db; + + /** How to run tasks in parallel. */ + private final BasicExecutor executor; + + /** + * @param txrx + * The transceiver for talking to the SpiNNaker machine. + * @param machine + * The description of the SpiNNaker machine. + * @param db + * The DSE database. + * @throws IOException + * If the transceiver can't talk to its sockets. + * @throws ProcessException + * If SpiNNaker rejects a message. + * @throws InterruptedException + * If communications are interrupted. + * @throws IllegalStateException + * If something really strange occurs with talking to the BMP; + * this constructor should not be doing that! + * @throws StorageException + * If the database cannot be read. + * @throws URISyntaxException + * If the proxy URI is specified but not valid. + */ + @MustBeClosed + @SuppressWarnings("MustBeClosed") + protected ExecuteDataSpecification(TransceiverInterface txrx, + Machine machine, DSEDatabaseEngine db) + throws IOException, ProcessException, InterruptedException, + StorageException, URISyntaxException { + super((db == null) ? null : txrx, machine); + this.db = db; + this.executor = new BasicExecutor(PARALLEL_SIZE); + } + + @Override + public final void close() throws IOException, InterruptedException { + if (txrx != null) { + txrx.close(); + } + executor.close(); + } + + /** + * Run the tasks in parallel. Submits to {@link #executor} and detoxifies + * the exceptions. + * + * @param tasks + * The tasks to run. + * @param mapper + * Gets how to implement a task. + * @throws StorageException + * If the database can't be talked to. + * @throws IOException + * If the transceiver can't talk to its sockets. + * @throws ProcessException + * If SpiNNaker rejects a message. + * @throws DataSpecificationException + * If a data specification in the database is invalid. + * @throws InterruptedException + * If communications are interrupted. + * @throws IllegalStateException + * If an unexpected exception occurs in any of the parallel + * tasks. + */ + protected final void processTasksInParallel(List tasks, + Function mapper) throws StorageException, + IOException, ProcessException, DataSpecificationException, + InterruptedException { + try { + executor.submitTasks(tasks, mapper).awaitAndCombineExceptions(); + } catch (StorageException | IOException | ProcessException + | DataSpecificationException | InterruptedException + | RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("unexpected exception", e); + } + } +} diff --git a/SpiNNaker-front-end/src/test/resources/gather.json b/SpiNNaker-front-end/src/test/resources/gather.json index 8aa16f57d5..5165c09f03 100644 --- a/SpiNNaker-front-end/src/test/resources/gather.json +++ b/SpiNNaker-front-end/src/test/resources/gather.json @@ -1 +1 @@ -[{"x": 0, "y": 0, "p": 1, "iptag": {"x": 0, "y": 0, "boardAddress": "192.168.240.253", "targetAddress": "localhost", "stripSDP": true, "tagID": 1, "trafficIdentifier": "DATA_SPEED_UP"}, "monitors": [{"x": 0, "y": 0, "p": 2, "placements": [{"x": 0, "y": 0, "p": 3, "vertex": {"label": "pop_1:0:2", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1614021536}}, {"x": 0, "y": 0, "p": 4, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972308}}]}]}] \ No newline at end of file +[{"x": 0, "y": 0, "p": 1, "iptag": {"x": 0, "y": 0, "boardAddress": "192.168.240.253", "targetAddress": "localhost", "stripSDP": true, "tagID": 1, "trafficIdentifier": "DATA_SPEED_UP"}, "monitors": [{"x": 0, "y": 0, "p": 2, "placements": [{"x": 0, "y": 0, "p": 3, "vertex": {"label": "pop_1:0:2", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1614021536}}, {"x": 0, "y": 0, "p": 4, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972308}}]}]}] diff --git a/SpiNNaker-front-end/src/test/resources/machine.json b/SpiNNaker-front-end/src/test/resources/machine.json index 2fcb2c872b..4303670184 100644 --- a/SpiNNaker-front-end/src/test/resources/machine.json +++ b/SpiNNaker-front-end/src/test/resources/machine.json @@ -1,16 +1,16 @@ -{ - "width": 1, - "height": 1, - "root": [0, 0], - "ethernetResources": {}, - "standardResources": {}, - "chips": [ - [ - 0, 0, { - "cores": 1, - "ethernet": [0, 0], - "ipAddress": "127.0.0.1" - } - ] - ] -} +{ + "width": 1, + "height": 1, + "root": [0, 0], + "ethernetResources": {}, + "standardResources": {}, + "chips": [ + [ + 0, 0, { + "cores": 1, + "ethernet": [0, 0], + "ipAddress": "127.0.0.1" + } + ] + ] +} diff --git a/SpiNNaker-front-end/src/test/resources/simple.json b/SpiNNaker-front-end/src/test/resources/simple.json index f98d2d8f46..035b20721e 100644 --- a/SpiNNaker-front-end/src/test/resources/simple.json +++ b/SpiNNaker-front-end/src/test/resources/simple.json @@ -1,2 +1,2 @@ [{"x": 0, "y": 0, "p": 1, "vertex": {"label": "pop_1:0:0", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1612972372}}, - {"x": 0, "y": 0, "p": 2, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972632}}] \ No newline at end of file + {"x": 0, "y": 0, "p": 2, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972632}}] diff --git a/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict b/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict index 8c67b7c3b6..2c60c4ecb5 100644 --- a/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict +++ b/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict @@ -1,16 +1,16 @@ -# Copyright (c) 2022 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 -# -# http://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. -1,abc,-d-%d-e-%d-f-%d -2,abc,,d,%d,e,%d,f,%d -foo,abcde,-d-%d-e-%d-f-%d +# Copyright (c) 2022 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 +# +# http://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. +1,abc,-d-%d-e-%d-f-%d +2,abc,,d,%d,e,%d,f,%d +foo,abcde,-d-%d-e-%d-f-%d diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java index 5517a4759f..236edebbab 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java @@ -1,157 +1,157 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.Integer.compareUnsigned; -import static java.lang.String.format; - -import com.google.errorprone.annotations.Immutable; - -/** - * A location in SpiNNaker or BMP memory. Does not say which address space this - * is in. - * - * @author Donal Fellows - */ -@Immutable -public final class MemoryLocation implements Comparable { - /** Number of bytes in a SpiNNaker (ARM) word. */ - private static final int WORD_SIZE = 4; - - /** The zero memory location. Often means "no actual address". */ - public static final MemoryLocation NULL = new MemoryLocation(0); - - /** The actual location. */ - public final int address; - - /** @param address The actual location. */ - public MemoryLocation(int address) { - this.address = address; - } - - /** @param address The actual location. */ - public MemoryLocation(long address) { - this.address = convert(address); - } - - /** - * Add an offset to this location to get a new memory location. - * - * @param offset - * The offset to add. - * @return The new memory location. - */ - public MemoryLocation add(int offset) { - return new MemoryLocation(address + offset); - } - - /** - * Get the difference between this location and another. - * - * @param other - * The other location. - * @return This location's address minus the other location's address. - */ - public int diff(MemoryLocation other) { - return address - other.address; - } - - /** @return Whether this location is really {@linkplain #NULL null}. */ - public boolean isNull() { - return address == 0; - } - - /** - * How many bytes is this location's address above a word-aligned address? - * - * @return The number of bytes offset. - */ - public int subWordAlignment() { - return address % WORD_SIZE; - } - - /** @return Whether this is a word-aligned location. */ - public boolean isAligned() { - return subWordAlignment() == 0; - } - - @Override - public int hashCode() { - return address; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof MemoryLocation)) { - return false; - } - var o = (MemoryLocation) other; - return o.address == address; - } - - @Override - public int compareTo(MemoryLocation other) { - return compareUnsigned(address, other.address); - } - - /** - * Test if this location is less than another location. - * - * @param other - * The other location. - * @return True if this location's address comes before. - */ - public boolean lessThan(MemoryLocation other) { - return compareTo(other) < 0; - } - - /** - * Test if this location is greater than another location. - * - * @param other - * The other location. - * @return True if this location's address comes after. - */ - public boolean greaterThan(MemoryLocation other) { - return compareTo(other) > 0; - } - - @Override - public String toString() { - // Leading '0x' then exactly 8 hexadecimal characters; 10 chars total - return format("%#010x", address); - } - - /** Maximum legal SpiNNaker address. It's a 32-bit machine. */ - private static final long MAX_ADDR = 0xFFFFFFFFL; - - /** - * Convert an address to a 32-bit integer. - * - * @param baseAddress - * The address as a long. - * @return the address as an int. - * @throws IllegalArgumentException - * if the value is outside the unsigned 32-bit integer range. - */ - private static int convert(long baseAddress) { - if (baseAddress < 0 || baseAddress > MAX_ADDR) { - throw new IllegalArgumentException( - "address must be in 32-bit unsigned integer range"); - } - return (int) baseAddress; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.Integer.compareUnsigned; +import static java.lang.String.format; + +import com.google.errorprone.annotations.Immutable; + +/** + * A location in SpiNNaker or BMP memory. Does not say which address space this + * is in. + * + * @author Donal Fellows + */ +@Immutable +public final class MemoryLocation implements Comparable { + /** Number of bytes in a SpiNNaker (ARM) word. */ + private static final int WORD_SIZE = 4; + + /** The zero memory location. Often means "no actual address". */ + public static final MemoryLocation NULL = new MemoryLocation(0); + + /** The actual location. */ + public final int address; + + /** @param address The actual location. */ + public MemoryLocation(int address) { + this.address = address; + } + + /** @param address The actual location. */ + public MemoryLocation(long address) { + this.address = convert(address); + } + + /** + * Add an offset to this location to get a new memory location. + * + * @param offset + * The offset to add. + * @return The new memory location. + */ + public MemoryLocation add(int offset) { + return new MemoryLocation(address + offset); + } + + /** + * Get the difference between this location and another. + * + * @param other + * The other location. + * @return This location's address minus the other location's address. + */ + public int diff(MemoryLocation other) { + return address - other.address; + } + + /** @return Whether this location is really {@linkplain #NULL null}. */ + public boolean isNull() { + return address == 0; + } + + /** + * How many bytes is this location's address above a word-aligned address? + * + * @return The number of bytes offset. + */ + public int subWordAlignment() { + return address % WORD_SIZE; + } + + /** @return Whether this is a word-aligned location. */ + public boolean isAligned() { + return subWordAlignment() == 0; + } + + @Override + public int hashCode() { + return address; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof MemoryLocation)) { + return false; + } + var o = (MemoryLocation) other; + return o.address == address; + } + + @Override + public int compareTo(MemoryLocation other) { + return compareUnsigned(address, other.address); + } + + /** + * Test if this location is less than another location. + * + * @param other + * The other location. + * @return True if this location's address comes before. + */ + public boolean lessThan(MemoryLocation other) { + return compareTo(other) < 0; + } + + /** + * Test if this location is greater than another location. + * + * @param other + * The other location. + * @return True if this location's address comes after. + */ + public boolean greaterThan(MemoryLocation other) { + return compareTo(other) > 0; + } + + @Override + public String toString() { + // Leading '0x' then exactly 8 hexadecimal characters; 10 chars total + return format("%#010x", address); + } + + /** Maximum legal SpiNNaker address. It's a 32-bit machine. */ + private static final long MAX_ADDR = 0xFFFFFFFFL; + + /** + * Convert an address to a 32-bit integer. + * + * @param baseAddress + * The address as a long. + * @return the address as an int. + * @throws IllegalArgumentException + * if the value is outside the unsigned 32-bit integer range. + */ + private static int convert(long baseAddress) { + if (baseAddress < 0 || baseAddress > MAX_ADDR) { + throw new IllegalArgumentException( + "address must be in 32-bit unsigned integer range"); + } + return (int) baseAddress; + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java index 6f7af70906..3d1c57a8da 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_Y; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Positive; - -/** - * Validates that a machine's height (in chips) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(MAX_Y + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidMachineHeight { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "machine height (${validatedValue}) " - + "must be at least 1 and no more than 256"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_Y; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; + +/** + * Validates that a machine's height (in chips) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(MAX_Y + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidMachineHeight { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "machine height (${validatedValue}) " + + "must be at least 1 and no more than 256"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java index d91e15fb83..6a4bd50522 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_X; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Positive; - -/** - * Validates that a machine's width (in chips) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(MAX_X + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidMachineWidth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "machine width (${validatedValue}) " - + "must be at least 1 and no more than 256"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_X; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; + +/** + * Validates that a machine's width (in chips) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(MAX_X + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidMachineWidth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "machine width (${validatedValue}) " + + "must be at least 1 and no more than 256"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java index 186628564d..43f2acf26e 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip processor number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.PROCESSORS_PER_CHIP - 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidP { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "processor number (${validatedValue}) " - + "must be at least 0 and no more than 17"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip processor number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.PROCESSORS_PER_CHIP - 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidP { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "processor number (${validatedValue}) " + + "must be at least 0 and no more than 17"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java index 9c66281df1..a9ce17bac0 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip X coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.MAX_X) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidX { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "X coordinate (${validatedValue}) " - + "must be at least 0 and no more than 255"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip X coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.MAX_X) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidX { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "X coordinate (${validatedValue}) " + + "must be at least 0 and no more than 255"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java index a135977967..f30100cc77 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip Y coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.MAX_Y) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidY { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Y coordinate (${validatedValue}) " - + "must be at least 0 and no more than 255"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip Y coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.MAX_Y) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidY { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Y coordinate (${validatedValue}) " + + "must be at least 0 and no more than 255"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 80cb9e07d9..64e9a754c8 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.google.errorprone.annotations.Immutable; - -/** - * A simple description of a BMP to talk to. Supports equality and being used as - * a hash key. - *

- * Although every board technically has a BMP, they are managed at the level of - * a frame (when a sufficient quantity of boards is used, typically but not - * necessarily 24). Cabinets contain frames. - * - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"cabinet": 3, "frame": 2}
- * and can be deserialized from that, or: - *
{"c": 3, "f": 2}
- * It can also accept being deserialised from a JSON array, for a more compact - * notation: - *
[3, 2]
- * Finally, it can also be deserialised from the string form created by the - * {@link #toString()} method: - *
[c:3,f:2]
- * - * @author Donal Fellows - */ -@Immutable -@JsonDeserialize(using = BMPCoords.Deserializer.class) -public final class BMPCoords implements Comparable { - /** Parses the result of {@link #toString()}. */ - private static final Pattern PATTERN = - Pattern.compile("^\\[c:(\\d+),f:(\\d+)\\]$"); - - /** The ID of the cabinet that contains the frame that contains the BMPs. */ - @ValidCabinetNumber - public final int cabinet; - - /** - * The ID of the frame that contains the master BMP. Frames are contained - * within a cabinet. - */ - @ValidFrameNumber - public final int frame; - - /** - * Create an instance. - * - * @param cabinet - * Cabinet number. - * @param frame - * Frame number. - */ - public BMPCoords(int cabinet, int frame) { - this.cabinet = cabinet; - this.frame = frame; - } - - /** - * Create an instance from its serial form. This is the form produced by - * {@link #toString()}. The serial form (where the numbers may vary) is: - * - *
-	 * [c:34,f:12]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public BMPCoords(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException("bad argument: " + serialForm); - } - int idx = 0; - cabinet = parseInt(m.group(++idx)); - frame = parseInt(m.group(++idx)); - } - - /** - * @return The ID of the cabinet that contains the frame that contains the - * BMPs. - */ - public int getCabinet() { - return cabinet; - } - - /** - * @return The ID of the frame that contains the master BMP. Frames are - * contained within a cabinet. - */ - public int getFrame() { - return frame; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof BMPCoords) { - var other = (BMPCoords) obj; - return cabinet == other.cabinet && frame == other.frame; - } - return false; - } - - @Override - public int hashCode() { - return cabinet * 5 + frame; - } - - @Override - public String toString() { - return "[c:" + cabinet + ",f:" + frame + "]"; - } - - @Override - public int compareTo(BMPCoords other) { - int cmp = compare(cabinet, other.cabinet); - if (cmp != 0) { - return cmp; - } - return compare(frame, other.frame); - } - - /** JSON deserializer for {@link BMPCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(BMPCoords.class); - } - - @Override - BMPCoords deserializeArray() throws IOException { - int c = getNextIntOfArray(); - int f = getNextIntOfArray(); - requireEndOfArray(); - return new BMPCoords(c, f); - } - - @Override - BMPCoords deserializeObject() throws IOException { - Integer c = null, f = null; - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "cabinet": - case "c": - c = requireSetOnceInt(name, c); - break; - case "frame": - case "f": - f = requireSetOnceInt(name, f); - break; - default: - unknownProperty(name); - } - } - if (c == null || f == null) { - missingProperty("c", c, "f", f); - } - return new BMPCoords(c, f); - } - - @Override - BMPCoords deserializeString(String string) { - return new BMPCoords(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("c", "f"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.errorprone.annotations.Immutable; + +/** + * A simple description of a BMP to talk to. Supports equality and being used as + * a hash key. + *

+ * Although every board technically has a BMP, they are managed at the level of + * a frame (when a sufficient quantity of boards is used, typically but not + * necessarily 24). Cabinets contain frames. + * + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"cabinet": 3, "frame": 2}
+ * and can be deserialized from that, or: + *
{"c": 3, "f": 2}
+ * It can also accept being deserialised from a JSON array, for a more compact + * notation: + *
[3, 2]
+ * Finally, it can also be deserialised from the string form created by the + * {@link #toString()} method: + *
[c:3,f:2]
+ * + * @author Donal Fellows + */ +@Immutable +@JsonDeserialize(using = BMPCoords.Deserializer.class) +public final class BMPCoords implements Comparable { + /** Parses the result of {@link #toString()}. */ + private static final Pattern PATTERN = + Pattern.compile("^\\[c:(\\d+),f:(\\d+)\\]$"); + + /** The ID of the cabinet that contains the frame that contains the BMPs. */ + @ValidCabinetNumber + public final int cabinet; + + /** + * The ID of the frame that contains the master BMP. Frames are contained + * within a cabinet. + */ + @ValidFrameNumber + public final int frame; + + /** + * Create an instance. + * + * @param cabinet + * Cabinet number. + * @param frame + * Frame number. + */ + public BMPCoords(int cabinet, int frame) { + this.cabinet = cabinet; + this.frame = frame; + } + + /** + * Create an instance from its serial form. This is the form produced by + * {@link #toString()}. The serial form (where the numbers may vary) is: + * + *
+	 * [c:34,f:12]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public BMPCoords(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException("bad argument: " + serialForm); + } + int idx = 0; + cabinet = parseInt(m.group(++idx)); + frame = parseInt(m.group(++idx)); + } + + /** + * @return The ID of the cabinet that contains the frame that contains the + * BMPs. + */ + public int getCabinet() { + return cabinet; + } + + /** + * @return The ID of the frame that contains the master BMP. Frames are + * contained within a cabinet. + */ + public int getFrame() { + return frame; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BMPCoords) { + var other = (BMPCoords) obj; + return cabinet == other.cabinet && frame == other.frame; + } + return false; + } + + @Override + public int hashCode() { + return cabinet * 5 + frame; + } + + @Override + public String toString() { + return "[c:" + cabinet + ",f:" + frame + "]"; + } + + @Override + public int compareTo(BMPCoords other) { + int cmp = compare(cabinet, other.cabinet); + if (cmp != 0) { + return cmp; + } + return compare(frame, other.frame); + } + + /** JSON deserializer for {@link BMPCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(BMPCoords.class); + } + + @Override + BMPCoords deserializeArray() throws IOException { + int c = getNextIntOfArray(); + int f = getNextIntOfArray(); + requireEndOfArray(); + return new BMPCoords(c, f); + } + + @Override + BMPCoords deserializeObject() throws IOException { + Integer c = null, f = null; + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "cabinet": + case "c": + c = requireSetOnceInt(name, c); + break; + case "frame": + case "f": + f = requireSetOnceInt(name, f); + break; + default: + unknownProperty(name); + } + } + if (c == null || f == null) { + missingProperty("c", c, "f", f); + } + return new BMPCoords(c, f); + } + + @Override + BMPCoords deserializeString(String string) { + return new BMPCoords(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("c", "f"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java index 8f6c2981c6..c93436a0db 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java @@ -1,203 +1,203 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import com.google.errorprone.annotations.ForOverride; -import com.google.errorprone.annotations.FormatMethod; - -/** - * A helper class for JSON deserializers. - * - * @param - * The type of values the deserializer deserializes. - */ -@SuppressWarnings("serial") -abstract class DeserializerHelper extends StdDeserializer { - private static final ThreadLocal CONTEXT = - new ThreadLocal<>(); - - private static final ThreadLocal PARSER = new ThreadLocal<>(); - - protected DeserializerHelper(Class cls) { - super(cls); - } - - @Override - public final T deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException { - try { - CONTEXT.set(ctxt); - PARSER.set(p); - switch (p.currentToken()) { - case START_ARRAY: - return deserializeArray(); - case START_OBJECT: - return deserializeObject(); - case VALUE_STRING: - return deserializeString(p.getValueAsString()); - default: - ctxt.handleUnexpectedToken(_valueClass, p); - return null; - } - } finally { - CONTEXT.remove(); - PARSER.remove(); - } - } - - /** - * Deserialize an array to an instance. - * - * @return The instance - * @throws IOException - * On failure - */ - @ForOverride - abstract T deserializeArray() throws IOException; - - /** - * Deserialize an object to an instance. - * - * @return The instance - * @throws IOException - * On failure - */ - @ForOverride - abstract T deserializeObject() throws IOException; - - /** - * Deserialize a string to an instance. - * - * @param string - * The string, already extracted. - * @return The instance - * @throws IllegalArgumentException - * On failure - */ - @ForOverride - abstract T deserializeString(String string); - - /** - * Throw an exception because of an unexpected token. - * - * @param cls - * What we were trying to instantiate. - * @throws IOException - * The exception always thrown. - */ - private void unexpectedToken(Class cls) throws IOException { - CONTEXT.get().handleUnexpectedToken(cls, PARSER.get()); - } - - /** - * Throw an exception because of an input mismatch. - * - * @param msg - * Used to describe the problem. - * @param args - * Values to substitute in. - * @throws IOException - * The exception always thrown. - */ - @FormatMethod - private void inputMismatch(String msg, Object... args) - throws IOException { - CONTEXT.get().reportInputMismatch(_valueClass, msg, args); - } - - /** - * Throw an exception because of an unknown property. - * - * @param name - * The unknown property name. - * @throws IOException - * The exception always thrown. - */ - void unknownProperty(String name) throws IOException { - CONTEXT.get().handleUnknownProperty(PARSER.get(), this, _valueClass, - name); - } - - int getNextIntOfArray() throws IOException { - var p = PARSER.get(); - if (!p.nextToken().isNumeric()) { - unexpectedToken(int.class); - } - return p.getIntValue(); - } - - String getNextFieldName() throws IOException { - var p = PARSER.get(); - var name = p.nextFieldName(); - if (name == null) { - if (!p.currentToken().isStructEnd()) { - unexpectedToken(_valueClass); - } - } - return name; - } - - void requireEndOfArray() throws IOException { - var p = PARSER.get(); - if (!p.nextToken().isStructEnd()) { - unexpectedToken(_valueClass); - } - } - - int requireSetOnceInt(String name, Integer current) throws IOException { - if (current != null) { - inputMismatch("Duplicate property '%s'", name); - } - return PARSER.get().nextIntValue(0); - } - - void missingProperty(String n1, Object v1) throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } - } - - void missingProperty(String n1, Object v1, String n2, Object v2) - throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } else if (v2 == null) { - inputMismatch("Missing required property '%s'", n2); - } - } - - void missingProperty(String n1, Object v1, String n2, Object v2, String n3, - Object v3) throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } else if (v2 == null) { - inputMismatch("Missing required property '%s'", n2); - } else if (v3 == null) { - inputMismatch("Missing required property '%s'", n3); - } - } - - @Override - public final Boolean supportsUpdate(DeserializationConfig config) { - return Boolean.FALSE; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.google.errorprone.annotations.ForOverride; +import com.google.errorprone.annotations.FormatMethod; + +/** + * A helper class for JSON deserializers. + * + * @param + * The type of values the deserializer deserializes. + */ +@SuppressWarnings("serial") +abstract class DeserializerHelper extends StdDeserializer { + private static final ThreadLocal CONTEXT = + new ThreadLocal<>(); + + private static final ThreadLocal PARSER = new ThreadLocal<>(); + + protected DeserializerHelper(Class cls) { + super(cls); + } + + @Override + public final T deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException { + try { + CONTEXT.set(ctxt); + PARSER.set(p); + switch (p.currentToken()) { + case START_ARRAY: + return deserializeArray(); + case START_OBJECT: + return deserializeObject(); + case VALUE_STRING: + return deserializeString(p.getValueAsString()); + default: + ctxt.handleUnexpectedToken(_valueClass, p); + return null; + } + } finally { + CONTEXT.remove(); + PARSER.remove(); + } + } + + /** + * Deserialize an array to an instance. + * + * @return The instance + * @throws IOException + * On failure + */ + @ForOverride + abstract T deserializeArray() throws IOException; + + /** + * Deserialize an object to an instance. + * + * @return The instance + * @throws IOException + * On failure + */ + @ForOverride + abstract T deserializeObject() throws IOException; + + /** + * Deserialize a string to an instance. + * + * @param string + * The string, already extracted. + * @return The instance + * @throws IllegalArgumentException + * On failure + */ + @ForOverride + abstract T deserializeString(String string); + + /** + * Throw an exception because of an unexpected token. + * + * @param cls + * What we were trying to instantiate. + * @throws IOException + * The exception always thrown. + */ + private void unexpectedToken(Class cls) throws IOException { + CONTEXT.get().handleUnexpectedToken(cls, PARSER.get()); + } + + /** + * Throw an exception because of an input mismatch. + * + * @param msg + * Used to describe the problem. + * @param args + * Values to substitute in. + * @throws IOException + * The exception always thrown. + */ + @FormatMethod + private void inputMismatch(String msg, Object... args) + throws IOException { + CONTEXT.get().reportInputMismatch(_valueClass, msg, args); + } + + /** + * Throw an exception because of an unknown property. + * + * @param name + * The unknown property name. + * @throws IOException + * The exception always thrown. + */ + void unknownProperty(String name) throws IOException { + CONTEXT.get().handleUnknownProperty(PARSER.get(), this, _valueClass, + name); + } + + int getNextIntOfArray() throws IOException { + var p = PARSER.get(); + if (!p.nextToken().isNumeric()) { + unexpectedToken(int.class); + } + return p.getIntValue(); + } + + String getNextFieldName() throws IOException { + var p = PARSER.get(); + var name = p.nextFieldName(); + if (name == null) { + if (!p.currentToken().isStructEnd()) { + unexpectedToken(_valueClass); + } + } + return name; + } + + void requireEndOfArray() throws IOException { + var p = PARSER.get(); + if (!p.nextToken().isStructEnd()) { + unexpectedToken(_valueClass); + } + } + + int requireSetOnceInt(String name, Integer current) throws IOException { + if (current != null) { + inputMismatch("Duplicate property '%s'", name); + } + return PARSER.get().nextIntValue(0); + } + + void missingProperty(String n1, Object v1) throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } + } + + void missingProperty(String n1, Object v1, String n2, Object v2) + throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } else if (v2 == null) { + inputMismatch("Missing required property '%s'", n2); + } + } + + void missingProperty(String n1, Object v1, String n2, Object v2, String n3, + Object v3) throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } else if (v2 == null) { + inputMismatch("Missing required property '%s'", n2); + } else if (v3 == null) { + inputMismatch("Missing required property '%s'", n3); + } + } + + @Override + public final Boolean supportsUpdate(DeserializationConfig config) { + return Boolean.FALSE; + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java index 81887c239f..e349adbe66 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -/** - * Various limits. These are constrained by the requirement that each of the - * dimensions of the coordinates for a chip fit in an unsigned byte. - */ -interface Limits { - /** - * Max triad X coordinate. Any larger and the chips become unaddressible. - */ - int MAX_TRIAD_X = 20; - - /** - * Max triad Y coordinate. Any larger and the chips become unaddressible. - */ - int MAX_TRIAD_Y = 20; - - /** Max triad Z coordinate. */ - int MAX_TRIAD_Z = 2; - - /** - * Maximum cabinet number. Any larger than this will result in the - * underlying chips becoming unaddressible. - */ - int MAX_CABINET = 31; - - /** - * Maximum frame number. Any larger than this will result in the underlying - * chips becoming unaddressible. - */ - int MAX_FRAME = 31; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +/** + * Various limits. These are constrained by the requirement that each of the + * dimensions of the coordinates for a chip fit in an unsigned byte. + */ +interface Limits { + /** + * Max triad X coordinate. Any larger and the chips become unaddressible. + */ + int MAX_TRIAD_X = 20; + + /** + * Max triad Y coordinate. Any larger and the chips become unaddressible. + */ + int MAX_TRIAD_Y = 20; + + /** Max triad Z coordinate. */ + int MAX_TRIAD_Z = 2; + + /** + * Maximum cabinet number. Any larger than this will result in the + * underlying chips becoming unaddressible. + */ + int MAX_CABINET = 31; + + /** + * Maximum frame number. Any larger than this will result in the underlying + * chips becoming unaddressible. + */ + int MAX_FRAME = 31; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index d620fa629f..bfd2ab072f 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -1,208 +1,208 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.google.errorprone.annotations.Immutable; - -/** - * Physical board coordinates. The {@code cabinet} and {@code frame} (with - * multiple frames per cabinet) describe where a board is located within the - * physical layout of the machine (and also which BMP is managing it, as there - * is one managing BMP per frame). The {@code board} number says which board - * within the frame is being referred to. - * - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"cabinet": 3, "frame": 2, "board": 1}
- * and can be deserialized from that, or: - *
{"c": 3, "f": 2, "b": 1}
- * It can also accept being deserialised from a JSON array, for a more compact - * notation: - *
[3, 2, 1]
- * Finally, it can also be deserialised from the string form created by the - * {@link #toString()} method: - *
[c:3,f:2,b:1]
- * - * @author Donal Fellows - */ -@Immutable -@JsonDeserialize(using = PhysicalCoords.Deserializer.class) -public final class PhysicalCoords implements Comparable { - /** Cabinet number. */ - @ValidCabinetNumber - public final int c; - - /** Frame number. */ - @ValidFrameNumber - public final int f; - - /** Board number. */ - @ValidBoardNumber - public final int b; - - /** - * Create an instance. - * - * @param c - * Cabinet number. - * @param f - * Frame number. - * @param b - * Board number. - */ - @JsonCreator - public PhysicalCoords(@JsonProperty("c") int c, @JsonProperty("f") int f, - @JsonProperty("b") int b) { - this.c = c; - this.f = f; - this.b = b; - } - - private static final Pattern PATTERN = - Pattern.compile("^\\[c:(\\d+),f:(\\d+),b:(\\d+)\\]$"); - - /** - * Create an instance from its serial form. The serial form (where the - * numbers may vary) is: - * - *
-	 * [c:34,f:12,b:23]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public PhysicalCoords(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException("bad argument: " + serialForm); - } - int idx = 0; - c = parseInt(m.group(++idx)); - f = parseInt(m.group(++idx)); - b = parseInt(m.group(++idx)); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PhysicalCoords) { - var other = (PhysicalCoords) obj; - return c == other.c && f == other.f && b == other.b; - } - return false; - } - - @Override - public int hashCode() { - return c * 25 + f * 5 + b; - } - - @Override - public String toString() { - return "[c:" + c + ",f:" + f + ",b:" + b + "]"; - } - - /** - * @return The coordinates of the BMP that manages this board. - */ - @JsonIgnore - public BMPCoords getBmpCoords() { - return new BMPCoords(c, f); - } - - @Override - public int compareTo(PhysicalCoords other) { - int cmp = compare(c, other.c); - if (cmp != 0) { - return cmp; - } - cmp = compare(f, other.f); - if (cmp != 0) { - return cmp; - } - return compare(b, other.b); - } - - /** JSON deserializer for {@link PhysicalCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(PhysicalCoords.class); - } - - @Override - PhysicalCoords deserializeArray() throws IOException { - int c = getNextIntOfArray(); - int f = getNextIntOfArray(); - int b = getNextIntOfArray(); - requireEndOfArray(); - return new PhysicalCoords(c, f, b); - } - - @Override - PhysicalCoords deserializeObject() throws IOException { - Integer c = null, f = null, b = null; - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "cabinet": - case "c": - c = requireSetOnceInt(name, c); - break; - case "frame": - case "f": - f = requireSetOnceInt(name, f); - break; - case "board": - case "b": - b = requireSetOnceInt(name, b); - break; - default: - unknownProperty(name); - } - } - if (c == null || f == null || b == null) { - missingProperty("c", c, "f", f, "b", b); - } - return new PhysicalCoords(c, f, b); - } - - @Override - PhysicalCoords deserializeString(String string) { - return new PhysicalCoords(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("c", "f", "b"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.errorprone.annotations.Immutable; + +/** + * Physical board coordinates. The {@code cabinet} and {@code frame} (with + * multiple frames per cabinet) describe where a board is located within the + * physical layout of the machine (and also which BMP is managing it, as there + * is one managing BMP per frame). The {@code board} number says which board + * within the frame is being referred to. + * + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"cabinet": 3, "frame": 2, "board": 1}
+ * and can be deserialized from that, or: + *
{"c": 3, "f": 2, "b": 1}
+ * It can also accept being deserialised from a JSON array, for a more compact + * notation: + *
[3, 2, 1]
+ * Finally, it can also be deserialised from the string form created by the + * {@link #toString()} method: + *
[c:3,f:2,b:1]
+ * + * @author Donal Fellows + */ +@Immutable +@JsonDeserialize(using = PhysicalCoords.Deserializer.class) +public final class PhysicalCoords implements Comparable { + /** Cabinet number. */ + @ValidCabinetNumber + public final int c; + + /** Frame number. */ + @ValidFrameNumber + public final int f; + + /** Board number. */ + @ValidBoardNumber + public final int b; + + /** + * Create an instance. + * + * @param c + * Cabinet number. + * @param f + * Frame number. + * @param b + * Board number. + */ + @JsonCreator + public PhysicalCoords(@JsonProperty("c") int c, @JsonProperty("f") int f, + @JsonProperty("b") int b) { + this.c = c; + this.f = f; + this.b = b; + } + + private static final Pattern PATTERN = + Pattern.compile("^\\[c:(\\d+),f:(\\d+),b:(\\d+)\\]$"); + + /** + * Create an instance from its serial form. The serial form (where the + * numbers may vary) is: + * + *
+	 * [c:34,f:12,b:23]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public PhysicalCoords(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException("bad argument: " + serialForm); + } + int idx = 0; + c = parseInt(m.group(++idx)); + f = parseInt(m.group(++idx)); + b = parseInt(m.group(++idx)); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PhysicalCoords) { + var other = (PhysicalCoords) obj; + return c == other.c && f == other.f && b == other.b; + } + return false; + } + + @Override + public int hashCode() { + return c * 25 + f * 5 + b; + } + + @Override + public String toString() { + return "[c:" + c + ",f:" + f + ",b:" + b + "]"; + } + + /** + * @return The coordinates of the BMP that manages this board. + */ + @JsonIgnore + public BMPCoords getBmpCoords() { + return new BMPCoords(c, f); + } + + @Override + public int compareTo(PhysicalCoords other) { + int cmp = compare(c, other.c); + if (cmp != 0) { + return cmp; + } + cmp = compare(f, other.f); + if (cmp != 0) { + return cmp; + } + return compare(b, other.b); + } + + /** JSON deserializer for {@link PhysicalCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(PhysicalCoords.class); + } + + @Override + PhysicalCoords deserializeArray() throws IOException { + int c = getNextIntOfArray(); + int f = getNextIntOfArray(); + int b = getNextIntOfArray(); + requireEndOfArray(); + return new PhysicalCoords(c, f, b); + } + + @Override + PhysicalCoords deserializeObject() throws IOException { + Integer c = null, f = null, b = null; + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "cabinet": + case "c": + c = requireSetOnceInt(name, c); + break; + case "frame": + case "f": + f = requireSetOnceInt(name, f); + break; + case "board": + case "b": + b = requireSetOnceInt(name, b); + break; + default: + unknownProperty(name); + } + } + if (c == null || f == null || b == null) { + missingProperty("c", c, "f", f, "b", b); + } + return new PhysicalCoords(c, f, b); + } + + @Override + PhysicalCoords deserializeString(String string) { + return new PhysicalCoords(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("c", "f", "b"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index 2cd7337596..8e936a3b1d 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -1,230 +1,230 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** - * Triad coordinates. - * Boards are in groups of three (triads) that group together in a rectangular - * grid. The {@code x} and {@code y} coordinates say which group of three in the - * grid, and the {@code z} coordinate says which board within the group. The - * group is not itself rectangular, but tesselates on a rectangular grid. - *

- * To understand how the triad coordinate system works, consider this board - * layout (a classic 24 board machine, with wrap-arounds not shown): - *

- * 24-board layout - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"x": 3, "y": 2, "z": 1}
- * and can also be deserialized from that, but can also accept being - * deserialised from a JSON array: - *
[3, 2, 1]
- * and can also be deserialized from its {@linkplain #toString() string form}: - *
[x:3,y:2,z:1]
- * - * @author Donal Fellows - */ -@JsonDeserialize(using = TriadCoords.Deserializer.class) -public final class TriadCoords implements Comparable { - /** The width and height of a triad, in chips. */ - private static final int TRIAD_CHIP_SIZE = 12; - - private static final int TRIAD_MAJOR_OFFSET = 8; - - private static final int TRIAD_MINOR_OFFSET = 4; - - /** Parses the string produced by {@link #toString()}. */ - private static final Pattern PATTERN = - Pattern.compile("^\\[x:(\\d+),y:(\\d+),z:(\\d+)\\]$"); - - /** X coordinate of triad. */ - @ValidTriadX - public final int x; - - /** Y coordinate of triad. */ - @ValidTriadY - public final int y; - - /** Z coordinate of triad. */ - @ValidTriadZ - public final int z; - - /** - * Create an instance. - * - * @param x - * X coordinate. - * @param y - * Y coordinate. - * @param z - * Z coordinate. - */ - @JsonCreator - public TriadCoords(@JsonProperty("x") int x, @JsonProperty("y") int y, - @JsonProperty("z") int z) { - this.x = x; - this.y = y; - this.z = z; - } - - /** - * Create an instance from its serial form. The serial form (where the - * numbers may vary) is: - * - *
-	 * [x:3,y:5,z:2]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public TriadCoords(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException( - "bad argument: " + serialForm); - } - int idx = 0; - x = parseInt(m.group(++idx)); - y = parseInt(m.group(++idx)); - z = parseInt(m.group(++idx)); - } - - /** - * Convert these coordinates into a machine-global chip location. - * - * @return The chip location relative to the root of the machine. - */ - public ChipLocation asChipLocation() { - int rootX = x * TRIAD_CHIP_SIZE; - int rootY = y * TRIAD_CHIP_SIZE; - switch (z) { - case 1: - rootX += TRIAD_MAJOR_OFFSET; - rootY += TRIAD_MINOR_OFFSET; - break; - case 2: - rootX += TRIAD_MINOR_OFFSET; - rootY += TRIAD_MAJOR_OFFSET; - break; - case 0: - default: - break; - } - return new ChipLocation(rootX, rootY); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TriadCoords) { - var other = (TriadCoords) obj; - return x == other.x && y == other.y && z == other.z; - } - return false; - } - - @Override - public int hashCode() { - return x * 25 + y * 5 + z; - } - - @Override - public String toString() { - return "[x:" + x + ",y:" + y + ",z:" + z + "]"; - } - - @Override - public int compareTo(TriadCoords other) { - int cmp = compare(x, other.x); - if (cmp != 0) { - return cmp; - } - cmp = compare(y, other.y); - if (cmp != 0) { - return cmp; - } - return compare(z, other.z); - } - - /** JSON deserializer for {@link TriadCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(TriadCoords.class); - } - - @Override - TriadCoords deserializeArray() throws IOException { - int x = getNextIntOfArray(); - int y = getNextIntOfArray(); - int z = getNextIntOfArray(); - requireEndOfArray(); - return new TriadCoords(x, y, z); - } - - @Override - TriadCoords deserializeObject() throws IOException { - Integer x = null, y = null, z = null; - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "x": - x = requireSetOnceInt(name, x); - break; - case "y": - y = requireSetOnceInt(name, y); - break; - case "z": - z = requireSetOnceInt(name, z); - break; - default: - unknownProperty(name); - } - } - if (x == null || y == null || z == null) { - missingProperty("x", x, "y", y, "z", z); - } - return new TriadCoords(x, y, z); - } - - @Override - TriadCoords deserializeString(String string) { - return new TriadCoords(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("x", "y", "z"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** + * Triad coordinates. + * Boards are in groups of three (triads) that group together in a rectangular + * grid. The {@code x} and {@code y} coordinates say which group of three in the + * grid, and the {@code z} coordinate says which board within the group. The + * group is not itself rectangular, but tesselates on a rectangular grid. + *

+ * To understand how the triad coordinate system works, consider this board + * layout (a classic 24 board machine, with wrap-arounds not shown): + *

+ * 24-board layout + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"x": 3, "y": 2, "z": 1}
+ * and can also be deserialized from that, but can also accept being + * deserialised from a JSON array: + *
[3, 2, 1]
+ * and can also be deserialized from its {@linkplain #toString() string form}: + *
[x:3,y:2,z:1]
+ * + * @author Donal Fellows + */ +@JsonDeserialize(using = TriadCoords.Deserializer.class) +public final class TriadCoords implements Comparable { + /** The width and height of a triad, in chips. */ + private static final int TRIAD_CHIP_SIZE = 12; + + private static final int TRIAD_MAJOR_OFFSET = 8; + + private static final int TRIAD_MINOR_OFFSET = 4; + + /** Parses the string produced by {@link #toString()}. */ + private static final Pattern PATTERN = + Pattern.compile("^\\[x:(\\d+),y:(\\d+),z:(\\d+)\\]$"); + + /** X coordinate of triad. */ + @ValidTriadX + public final int x; + + /** Y coordinate of triad. */ + @ValidTriadY + public final int y; + + /** Z coordinate of triad. */ + @ValidTriadZ + public final int z; + + /** + * Create an instance. + * + * @param x + * X coordinate. + * @param y + * Y coordinate. + * @param z + * Z coordinate. + */ + @JsonCreator + public TriadCoords(@JsonProperty("x") int x, @JsonProperty("y") int y, + @JsonProperty("z") int z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Create an instance from its serial form. The serial form (where the + * numbers may vary) is: + * + *
+	 * [x:3,y:5,z:2]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public TriadCoords(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException( + "bad argument: " + serialForm); + } + int idx = 0; + x = parseInt(m.group(++idx)); + y = parseInt(m.group(++idx)); + z = parseInt(m.group(++idx)); + } + + /** + * Convert these coordinates into a machine-global chip location. + * + * @return The chip location relative to the root of the machine. + */ + public ChipLocation asChipLocation() { + int rootX = x * TRIAD_CHIP_SIZE; + int rootY = y * TRIAD_CHIP_SIZE; + switch (z) { + case 1: + rootX += TRIAD_MAJOR_OFFSET; + rootY += TRIAD_MINOR_OFFSET; + break; + case 2: + rootX += TRIAD_MINOR_OFFSET; + rootY += TRIAD_MAJOR_OFFSET; + break; + case 0: + default: + break; + } + return new ChipLocation(rootX, rootY); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TriadCoords) { + var other = (TriadCoords) obj; + return x == other.x && y == other.y && z == other.z; + } + return false; + } + + @Override + public int hashCode() { + return x * 25 + y * 5 + z; + } + + @Override + public String toString() { + return "[x:" + x + ",y:" + y + ",z:" + z + "]"; + } + + @Override + public int compareTo(TriadCoords other) { + int cmp = compare(x, other.x); + if (cmp != 0) { + return cmp; + } + cmp = compare(y, other.y); + if (cmp != 0) { + return cmp; + } + return compare(z, other.z); + } + + /** JSON deserializer for {@link TriadCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(TriadCoords.class); + } + + @Override + TriadCoords deserializeArray() throws IOException { + int x = getNextIntOfArray(); + int y = getNextIntOfArray(); + int z = getNextIntOfArray(); + requireEndOfArray(); + return new TriadCoords(x, y, z); + } + + @Override + TriadCoords deserializeObject() throws IOException { + Integer x = null, y = null, z = null; + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "x": + x = requireSetOnceInt(name, x); + break; + case "y": + y = requireSetOnceInt(name, y); + break; + case "z": + z = requireSetOnceInt(name, z); + break; + default: + unknownProperty(name); + } + } + if (x == null || y == null || z == null) { + missingProperty("x", x, "y", y, "z", z); + } + return new TriadCoords(x, y, z); + } + + @Override + TriadCoords deserializeString(String string) { + return new TriadCoords(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("x", "y", "z"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java index 995a40f034..7ff84378b7 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.BMPBoard.MAX_BOARD_NUMBER; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a board number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_BOARD_NUMBER) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidBoardNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "board number (${validatedValue}) " - + "must be in range 0-23"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.BMPBoard.MAX_BOARD_NUMBER; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a board number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_BOARD_NUMBER) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidBoardNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "board number (${validatedValue}) " + + "must be in range 0-23"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java index f53500b49e..dc35230d23 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_CABINET; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a cabinet number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_CABINET) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidCabinetNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "cabinet number (${validatedValue}) " - + "must be in range 0-31"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_CABINET; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a cabinet number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_CABINET) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidCabinetNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "cabinet number (${validatedValue}) " + + "must be in range 0-31"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java index ca600892db..89a597ad37 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_FRAME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a frame number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_FRAME) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidFrameNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "frame number (${validatedValue}) " - + "must be in range 0-31"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_FRAME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a frame number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_FRAME) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidFrameNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "frame number (${validatedValue}) " + + "must be in range 0-31"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java index 89b0f8c6fd..456a4be68c 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Positive; - -/** - * Validates that a machine's depth is in a sane range. Note that only machines - * with a single board typically have a depth other than 3, and the current - * implementation never uses a depth of 2. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_Z + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadDepth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad depth (${validatedValue}) " - + "must be at least 1 and no more than 3"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; + +/** + * Validates that a machine's depth is in a sane range. Note that only machines + * with a single board typically have a depth other than 3, and the current + * implementation never uses a depth of 2. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_Z + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadDepth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad depth (${validatedValue}) " + + "must be at least 1 and no more than 3"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java index 87168d87fa..08ad0f2703 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Positive; - -/** - * Validates that a machine's height (in triads) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_Y + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadHeight { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad height (${validatedValue}) " - + "must be at least 1 and no more than 21"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; + +/** + * Validates that a machine's height (in triads) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_Y + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadHeight { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad height (${validatedValue}) " + + "must be at least 1 and no more than 21"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java index f48b125783..69cf6c6b9e 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Positive; - -/** - * Validates that a machine's width (in triads) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_X + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadWidth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad width (${validatedValue}) " - + "must be at least 1 and no more than 21"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Positive; + +/** + * Validates that a machine's width (in triads) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_X + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadWidth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad width (${validatedValue}) " + + "must be at least 1 and no more than 21"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java index 76f407cef2..2991258203 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad X coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_X) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadX { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "X coordinate (${validatedValue}) " - + "must be at least 0 and no more than 63"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad X coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_X) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadX { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "X coordinate (${validatedValue}) " + + "must be at least 0 and no more than 63"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java index 8c074cc3ec..81419768af 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad Y coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_Y) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadY { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Y coordinate (${validatedValue}) " - + "must be at least 0 and no more than 63"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad Y coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_Y) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadY { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Y coordinate (${validatedValue}) " + + "must be at least 0 and no more than 63"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java index dcfa24717a..a402ea39cb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.Payload; -import jakarta.validation.ReportAsSingleViolation; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad Z coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_Z) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadZ { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Z coordinate (${validatedValue}) " - + "must be 0, 1, or 2"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import jakarta.validation.ReportAsSingleViolation; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad Z coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_Z) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadZ { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Z coordinate (${validatedValue}) " + + "must be 0, 1, or 2"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java index a299c226ce..2927f79bbb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2022 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 - * - * http://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. - */ -/** - * Classes relating to boards in a SpiNNaker machine. Note that boards - * themselves mostly not modelled, but their coordinates schemes are because - * they are used in many places. - */ -package uk.ac.manchester.spinnaker.machine.board; +/* + * Copyright (c) 2022 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 + * + * http://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. + */ +/** + * Classes relating to boards in a SpiNNaker machine. Note that boards + * themselves mostly not modelled, but their coordinates schemes are because + * they are used in many places. + */ +package uk.ac.manchester.spinnaker.machine.board; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java index f40264466d..2e2df55bff 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java @@ -1,103 +1,103 @@ -/* - * 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 - * - * http://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.machine.tags; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.Payload; - -/** - * Validates that a number looks like a tag identifier. Always accepts - * {@code null}. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = TagIDValidator.class) -public @interface TagID { - /** - * Whether to allow the SC&MP-dedicated tag. - * - * @return Whether 0 is allowed. - */ - boolean scamp() default false; - - /** - * Whether to also allow ephemeral tags. - * - * @return Whether 8-15 are allowed - */ - boolean ephemeral() default false; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad tag identifier"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} - -class TagIDValidator implements ConstraintValidator { - private static final int MAX_TAG = 7; - - private static final int MAX_EPHEMERAL = 15; - - private int min; - - private int max; - - @Override - public void initialize(TagID annotation) { - min = annotation.scamp() ? 0 : 1; - max = annotation.ephemeral() ? MAX_EPHEMERAL : MAX_TAG; - } - - @Override - public boolean isValid(Integer value, ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - return (value >= min) && (value <= max); - } -} +/* + * 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 + * + * http://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.machine.tags; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.Payload; + +/** + * Validates that a number looks like a tag identifier. Always accepts + * {@code null}. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = TagIDValidator.class) +public @interface TagID { + /** + * Whether to allow the SC&MP-dedicated tag. + * + * @return Whether 0 is allowed. + */ + boolean scamp() default false; + + /** + * Whether to also allow ephemeral tags. + * + * @return Whether 8-15 are allowed + */ + boolean ephemeral() default false; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad tag identifier"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} + +class TagIDValidator implements ConstraintValidator { + private static final int MAX_TAG = 7; + + private static final int MAX_EPHEMERAL = 15; + + private int min; + + private int max; + + @Override + public void initialize(TagID annotation) { + min = annotation.scamp() ? 0 : 1; + max = annotation.ephemeral() ? MAX_EPHEMERAL : MAX_TAG; + } + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + return (value >= min) && (value <= max); + } +} diff --git a/SpiNNaker-machine/src/test/resources/h40w16.json b/SpiNNaker-machine/src/test/resources/h40w16.json index d70130e002..0d66f329d1 100644 --- a/SpiNNaker-machine/src/test/resources/h40w16.json +++ b/SpiNNaker-machine/src/test/resources/h40w16.json @@ -1 +1 @@ -{"height": 40, "width": 16, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "10.11.197.9"}], [0, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [0, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.25"}], [0, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3, 4]}], [0, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.9"}], [0, 25, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 26, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 27, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [1, 4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0]}], [1, 2, {"cores": 17, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [1, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [1, 13, {"cores": 17, "ethernet": [0, 12]}], [1, 14, {"cores": 17, "ethernet": [0, 12]}], [1, 15, {"cores": 17, "ethernet": [0, 12]}], [1, 16, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [1, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [1, 25, {"cores": 17, "ethernet": [0, 24]}], [1, 26, {"cores": 17, "ethernet": [0, 24]}], [1, 27, {"cores": 17, "ethernet": [0, 24]}], [1, 28, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [2, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 4, 5]}], [2, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [5]}], [2, 3, {"cores": 17, "ethernet": [0, 0]}], [2, 4, {"cores": 17, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [2, 13, {"cores": 17, "ethernet": [0, 12]}], [2, 14, {"cores": 17, "ethernet": [0, 12]}], [2, 15, {"cores": 17, "ethernet": [0, 12]}], [2, 16, {"cores": 17, "ethernet": [0, 12]}], [2, 17, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [2, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [2, 25, {"cores": 17, "ethernet": [0, 24]}], [2, 26, {"cores": 17, "ethernet": [0, 24]}], [2, 27, {"cores": 17, "ethernet": [0, 24]}], [2, 28, {"cores": 17, "ethernet": [0, 24]}], [2, 29, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [3, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [3, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4]}], [3, 3, {"cores": 16, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [3, 13, {"cores": 17, "ethernet": [0, 12]}], [3, 14, {"cores": 17, "ethernet": [0, 12]}], [3, 15, {"cores": 17, "ethernet": [0, 12]}], [3, 16, {"cores": 17, "ethernet": [0, 12]}], [3, 17, {"cores": 17, "ethernet": [0, 12]}], [3, 18, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [3, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [3, 25, {"cores": 17, "ethernet": [0, 24]}], [3, 26, {"cores": 17, "ethernet": [0, 24]}], [3, 27, {"cores": 17, "ethernet": [0, 24]}], [3, 28, {"cores": 17, "ethernet": [0, 24]}], [3, 29, {"cores": 17, "ethernet": [0, 24]}], [3, 30, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [4, 0, {"cores": 16, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 17, "ethernet": [0, 0]}], [4, 2, {"cores": 17, "ethernet": [0, 0]}], [4, 3, {"cores": 17, "ethernet": [0, 0]}], [4, 4, {"cores": 17, "ethernet": [0, 0]}], [4, 5, {"cores": 17, "ethernet": [0, 0]}], [4, 6, {"cores": 17, "ethernet": [0, 0]}], [4, 7, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [4, 8, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4], "ipAddress": "10.11.197.73"}], [4, 9, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 10, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [4, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [1]}], [4, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [0]}], [4, 15, {"cores": 17, "ethernet": [0, 12]}], [4, 16, {"cores": 17, "ethernet": [0, 12]}], [4, 17, {"cores": 17, "ethernet": [0, 12]}], [4, 18, {"cores": 17, "ethernet": [0, 12]}], [4, 19, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [4, 20, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4], "ipAddress": "10.11.196.89"}], [4, 21, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4]}], [4, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1, 3, 4]}], [4, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 3, 4]}], [4, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4]}], [4, 25, {"cores": 17, "ethernet": [0, 24]}], [4, 26, {"cores": 17, "ethernet": [0, 24]}], [4, 27, {"cores": 17, "ethernet": [0, 24]}], [4, 28, {"cores": 17, "ethernet": [0, 24]}], [4, 29, {"cores": 17, "ethernet": [0, 24]}], [4, 30, {"cores": 17, "ethernet": [0, 24]}], [4, 31, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3]}], [4, 32, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4], "ipAddress": "10.11.196.73"}], [4, 33, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 34, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3, 4]}], [5, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 17, "ethernet": [0, 0]}], [5, 4, {"cores": 16, "ethernet": [0, 0]}], [5, 5, {"cores": 17, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 17, "ethernet": [0, 0]}], [5, 8, {"cores": 17, "ethernet": [4, 8]}], [5, 9, {"cores": 17, "ethernet": [4, 8]}], [5, 10, {"cores": 17, "ethernet": [4, 8]}], [5, 11, {"cores": 17, "ethernet": [4, 8]}], [5, 12, {"cores": 17, "ethernet": [4, 8]}], [5, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2]}], [5, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [5]}], [5, 16, {"cores": 17, "ethernet": [0, 12]}], [5, 17, {"cores": 17, "ethernet": [0, 12]}], [5, 18, {"cores": 17, "ethernet": [0, 12]}], [5, 19, {"cores": 17, "ethernet": [0, 12]}], [5, 20, {"cores": 17, "ethernet": [4, 20]}], [5, 21, {"cores": 17, "ethernet": [4, 20]}], [5, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [2]}], [5, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [5]}], [5, 25, {"cores": 17, "ethernet": [0, 24]}], [5, 26, {"cores": 17, "ethernet": [0, 24]}], [5, 27, {"cores": 17, "ethernet": [0, 24]}], [5, 28, {"cores": 17, "ethernet": [0, 24]}], [5, 29, {"cores": 17, "ethernet": [0, 24]}], [5, 30, {"cores": 17, "ethernet": [0, 24]}], [5, 31, {"cores": 17, "ethernet": [0, 24]}], [5, 32, {"cores": 17, "ethernet": [4, 32]}], [5, 33, {"cores": 17, "ethernet": [4, 32]}], [5, 34, {"cores": 17, "ethernet": [4, 32]}], [5, 35, {"cores": 17, "ethernet": [4, 32]}], [5, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [6, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 17, "ethernet": [0, 0]}], [6, 5, {"cores": 17, "ethernet": [0, 0]}], [6, 6, {"cores": 17, "ethernet": [0, 0]}], [6, 7, {"cores": 17, "ethernet": [0, 0]}], [6, 8, {"cores": 17, "ethernet": [4, 8]}], [6, 9, {"cores": 17, "ethernet": [4, 8]}], [6, 10, {"cores": 17, "ethernet": [4, 8]}], [6, 11, {"cores": 17, "ethernet": [4, 8]}], [6, 12, {"cores": 17, "ethernet": [4, 8]}], [6, 13, {"cores": 17, "ethernet": [4, 8]}], [6, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [6, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [6, 16, {"cores": 17, "ethernet": [0, 12]}], [6, 17, {"cores": 17, "ethernet": [0, 12]}], [6, 18, {"cores": 17, "ethernet": [0, 12]}], [6, 19, {"cores": 17, "ethernet": [0, 12]}], [6, 20, {"cores": 17, "ethernet": [4, 20]}], [6, 21, {"cores": 17, "ethernet": [4, 20]}], [6, 22, {"cores": 17, "ethernet": [4, 20]}], [6, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3]}], [6, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [4]}], [6, 25, {"cores": 17, "ethernet": [4, 20]}], [6, 26, {"cores": 17, "ethernet": [0, 24]}], [6, 27, {"cores": 17, "ethernet": [0, 24]}], [6, 28, {"cores": 17, "ethernet": [0, 24]}], [6, 29, {"cores": 17, "ethernet": [0, 24]}], [6, 30, {"cores": 17, "ethernet": [0, 24]}], [6, 31, {"cores": 17, "ethernet": [0, 24]}], [6, 32, {"cores": 17, "ethernet": [4, 32]}], [6, 33, {"cores": 17, "ethernet": [4, 32]}], [6, 34, {"cores": 17, "ethernet": [4, 32]}], [6, 35, {"cores": 17, "ethernet": [4, 32]}], [6, 36, {"cores": 17, "ethernet": [4, 32]}], [6, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [7, 4, {"cores": 17, "ethernet": [0, 0]}], [7, 5, {"cores": 17, "ethernet": [0, 0]}], [7, 6, {"cores": 17, "ethernet": [0, 0]}], [7, 7, {"cores": 17, "ethernet": [0, 0]}], [7, 8, {"cores": 17, "ethernet": [4, 8]}], [7, 9, {"cores": 17, "ethernet": [4, 8]}], [7, 10, {"cores": 17, "ethernet": [4, 8]}], [7, 11, {"cores": 17, "ethernet": [4, 8]}], [7, 12, {"cores": 17, "ethernet": [4, 8]}], [7, 13, {"cores": 17, "ethernet": [4, 8]}], [7, 14, {"cores": 17, "ethernet": [4, 8]}], [7, 15, {"cores": 17, "ethernet": [0, 12]}], [7, 16, {"cores": 17, "ethernet": [0, 12]}], [7, 17, {"cores": 17, "ethernet": [0, 12]}], [7, 18, {"cores": 17, "ethernet": [0, 12]}], [7, 19, {"cores": 17, "ethernet": [0, 12]}], [7, 20, {"cores": 17, "ethernet": [4, 20]}], [7, 21, {"cores": 17, "ethernet": [4, 20]}], [7, 22, {"cores": 17, "ethernet": [4, 20]}], [7, 23, {"cores": 17, "ethernet": [4, 20]}], [7, 24, {"cores": 17, "ethernet": [4, 20]}], [7, 25, {"cores": 17, "ethernet": [4, 20]}], [7, 26, {"cores": 17, "ethernet": [4, 20]}], [7, 27, {"cores": 17, "ethernet": [0, 24]}], [7, 28, {"cores": 17, "ethernet": [0, 24]}], [7, 29, {"cores": 17, "ethernet": [0, 24]}], [7, 30, {"cores": 17, "ethernet": [0, 24]}], [7, 31, {"cores": 17, "ethernet": [0, 24]}], [7, 32, {"cores": 17, "ethernet": [4, 32]}], [7, 33, {"cores": 17, "ethernet": [4, 32]}], [7, 34, {"cores": 17, "ethernet": [4, 32]}], [7, 35, {"cores": 17, "ethernet": [4, 32]}], [7, 36, {"cores": 17, "ethernet": [4, 32]}], [7, 37, {"cores": 17, "ethernet": [4, 32]}], [7, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [8, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [5], "ipAddress": "10.11.197.137"}], [8, 5, {"cores": 17, "ethernet": [8, 4]}], [8, 6, {"cores": 17, "ethernet": [8, 4]}], [8, 7, {"cores": 17, "ethernet": [8, 4]}], [8, 8, {"cores": 17, "ethernet": [4, 8]}], [8, 9, {"cores": 17, "ethernet": [4, 8]}], [8, 10, {"cores": 17, "ethernet": [4, 8]}], [8, 11, {"cores": 17, "ethernet": [4, 8]}], [8, 12, {"cores": 17, "ethernet": [4, 8]}], [8, 13, {"cores": 17, "ethernet": [4, 8]}], [8, 14, {"cores": 17, "ethernet": [4, 8]}], [8, 15, {"cores": 17, "ethernet": [4, 8]}], [8, 16, {"cores": 17, "ethernet": [8, 16], "ipAddress": "10.11.196.153"}], [8, 17, {"cores": 17, "ethernet": [8, 16]}], [8, 18, {"cores": 17, "ethernet": [8, 16]}], [8, 19, {"cores": 17, "ethernet": [8, 16]}], [8, 20, {"cores": 17, "ethernet": [4, 20]}], [8, 21, {"cores": 17, "ethernet": [4, 20]}], [8, 22, {"cores": 17, "ethernet": [4, 20]}], [8, 23, {"cores": 17, "ethernet": [4, 20]}], [8, 24, {"cores": 17, "ethernet": [4, 20]}], [8, 25, {"cores": 17, "ethernet": [4, 20]}], [8, 26, {"cores": 17, "ethernet": [4, 20]}], [8, 27, {"cores": 17, "ethernet": [4, 20]}], [8, 28, {"cores": 17, "ethernet": [8, 28], "ipAddress": "10.11.196.137"}], [8, 29, {"cores": 17, "ethernet": [8, 28]}], [8, 30, {"cores": 17, "ethernet": [8, 28]}], [8, 31, {"cores": 17, "ethernet": [8, 28]}], [8, 32, {"cores": 17, "ethernet": [4, 32]}], [8, 33, {"cores": 17, "ethernet": [4, 32]}], [8, 34, {"cores": 17, "ethernet": [4, 32]}], [8, 35, {"cores": 17, "ethernet": [4, 32]}], [8, 36, {"cores": 17, "ethernet": [4, 32]}], [8, 37, {"cores": 17, "ethernet": [4, 32]}], [8, 38, {"cores": 17, "ethernet": [4, 32]}], [8, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2, 3]}], [9, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [9, 5, {"cores": 17, "ethernet": [8, 4]}], [9, 6, {"cores": 17, "ethernet": [8, 4]}], [9, 7, {"cores": 17, "ethernet": [8, 4]}], [9, 8, {"cores": 17, "ethernet": [8, 4]}], [9, 9, {"cores": 17, "ethernet": [4, 8]}], [9, 10, {"cores": 17, "ethernet": [4, 8]}], [9, 11, {"cores": 17, "ethernet": [4, 8]}], [9, 12, {"cores": 17, "ethernet": [4, 8]}], [9, 13, {"cores": 17, "ethernet": [4, 8]}], [9, 14, {"cores": 17, "ethernet": [4, 8]}], [9, 15, {"cores": 17, "ethernet": [4, 8]}], [9, 16, {"cores": 17, "ethernet": [8, 16]}], [9, 17, {"cores": 17, "ethernet": [8, 16]}], [9, 18, {"cores": 17, "ethernet": [8, 16]}], [9, 19, {"cores": 17, "ethernet": [8, 16]}], [9, 20, {"cores": 17, "ethernet": [8, 16]}], [9, 21, {"cores": 17, "ethernet": [4, 20]}], [9, 22, {"cores": 17, "ethernet": [4, 20]}], [9, 23, {"cores": 17, "ethernet": [4, 20]}], [9, 24, {"cores": 17, "ethernet": [4, 20]}], [9, 25, {"cores": 17, "ethernet": [4, 20]}], [9, 26, {"cores": 17, "ethernet": [4, 20]}], [9, 27, {"cores": 17, "ethernet": [4, 20]}], [9, 28, {"cores": 17, "ethernet": [8, 28]}], [9, 29, {"cores": 17, "ethernet": [8, 28]}], [9, 30, {"cores": 17, "ethernet": [8, 28]}], [9, 31, {"cores": 17, "ethernet": [8, 28]}], [9, 32, {"cores": 17, "ethernet": [8, 28]}], [9, 33, {"cores": 17, "ethernet": [4, 32]}], [9, 34, {"cores": 17, "ethernet": [4, 32]}], [9, 35, {"cores": 17, "ethernet": [4, 32]}], [9, 36, {"cores": 17, "ethernet": [4, 32]}], [9, 37, {"cores": 17, "ethernet": [4, 32]}], [9, 38, {"cores": 15, "ethernet": [4, 32]}], [9, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [10, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [10, 5, {"cores": 17, "ethernet": [8, 4]}], [10, 6, {"cores": 17, "ethernet": [8, 4]}], [10, 7, {"cores": 17, "ethernet": [8, 4]}], [10, 8, {"cores": 17, "ethernet": [8, 4]}], [10, 9, {"cores": 17, "ethernet": [8, 4]}], [10, 10, {"cores": 17, "ethernet": [4, 8]}], [10, 11, {"cores": 17, "ethernet": [4, 8]}], [10, 12, {"cores": 17, "ethernet": [4, 8]}], [10, 13, {"cores": 17, "ethernet": [4, 8]}], [10, 14, {"cores": 17, "ethernet": [4, 8]}], [10, 15, {"cores": 17, "ethernet": [4, 8]}], [10, 16, {"cores": 17, "ethernet": [8, 16]}], [10, 17, {"cores": 17, "ethernet": [8, 16]}], [10, 18, {"cores": 17, "ethernet": [8, 16]}], [10, 19, {"cores": 17, "ethernet": [8, 16]}], [10, 20, {"cores": 17, "ethernet": [8, 16]}], [10, 21, {"cores": 17, "ethernet": [8, 16]}], [10, 22, {"cores": 17, "ethernet": [4, 20]}], [10, 23, {"cores": 17, "ethernet": [4, 20]}], [10, 24, {"cores": 17, "ethernet": [4, 20]}], [10, 25, {"cores": 17, "ethernet": [4, 20]}], [10, 26, {"cores": 17, "ethernet": [4, 20]}], [10, 27, {"cores": 17, "ethernet": [4, 20]}], [10, 28, {"cores": 17, "ethernet": [8, 28]}], [10, 29, {"cores": 17, "ethernet": [8, 28]}], [10, 30, {"cores": 17, "ethernet": [8, 28]}], [10, 31, {"cores": 17, "ethernet": [8, 28]}], [10, 32, {"cores": 17, "ethernet": [8, 28]}], [10, 33, {"cores": 17, "ethernet": [8, 28]}], [10, 34, {"cores": 17, "ethernet": [4, 32]}], [10, 35, {"cores": 17, "ethernet": [4, 32]}], [10, 36, {"cores": 17, "ethernet": [4, 32]}], [10, 37, {"cores": 17, "ethernet": [4, 32]}], [10, 38, {"cores": 17, "ethernet": [4, 32]}], [10, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [11, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [11, 5, {"cores": 17, "ethernet": [8, 4]}], [11, 6, {"cores": 17, "ethernet": [8, 4]}], [11, 7, {"cores": 17, "ethernet": [8, 4]}], [11, 8, {"cores": 17, "ethernet": [8, 4]}], [11, 9, {"cores": 17, "ethernet": [8, 4]}], [11, 10, {"cores": 17, "ethernet": [8, 4]}], [11, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [1]}], [11, 12, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 13, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 14, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 15, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0]}], [11, 16, {"cores": 17, "ethernet": [8, 16]}], [11, 17, {"cores": 17, "ethernet": [8, 16]}], [11, 18, {"cores": 17, "ethernet": [8, 16]}], [11, 19, {"cores": 17, "ethernet": [8, 16]}], [11, 20, {"cores": 17, "ethernet": [8, 16]}], [11, 21, {"cores": 17, "ethernet": [8, 16]}], [11, 22, {"cores": 17, "ethernet": [8, 16]}], [11, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1]}], [11, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 25, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 26, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 27, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0]}], [11, 28, {"cores": 17, "ethernet": [8, 28]}], [11, 29, {"cores": 17, "ethernet": [8, 28]}], [11, 30, {"cores": 17, "ethernet": [8, 28]}], [11, 31, {"cores": 17, "ethernet": [8, 28]}], [11, 32, {"cores": 17, "ethernet": [8, 28]}], [11, 33, {"cores": 17, "ethernet": [8, 28]}], [11, 34, {"cores": 17, "ethernet": [8, 28]}], [11, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1]}], [11, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1, 2]}], [12, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 4, 5]}], [12, 5, {"cores": 17, "ethernet": [8, 4]}], [12, 6, {"cores": 17, "ethernet": [8, 4]}], [12, 7, {"cores": 17, "ethernet": [8, 4]}], [12, 8, {"cores": 17, "ethernet": [8, 4]}], [12, 9, {"cores": 17, "ethernet": [8, 4]}], [12, 10, {"cores": 17, "ethernet": [8, 4]}], [12, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [12, 16, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 17, {"cores": 17, "ethernet": [8, 16]}], [12, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [2]}], [12, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 20, {"cores": 17, "ethernet": [8, 16]}], [12, 21, {"cores": 17, "ethernet": [8, 16]}], [12, 22, {"cores": 17, "ethernet": [8, 16]}], [12, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [12, 28, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [12, 29, {"cores": 17, "ethernet": [8, 28]}], [12, 30, {"cores": 17, "ethernet": [8, 28]}], [12, 31, {"cores": 17, "ethernet": [8, 28]}], [12, 32, {"cores": 17, "ethernet": [8, 28]}], [12, 33, {"cores": 17, "ethernet": [8, 28]}], [12, 34, {"cores": 17, "ethernet": [8, 28]}], [12, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [13, 5, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [13, 6, {"cores": 17, "ethernet": [8, 4]}], [13, 7, {"cores": 17, "ethernet": [8, 4]}], [13, 8, {"cores": 17, "ethernet": [8, 4]}], [13, 9, {"cores": 17, "ethernet": [8, 4]}], [13, 10, {"cores": 17, "ethernet": [8, 4]}], [13, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [13, 17, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [13, 18, {"cores": 17, "ethernet": [8, 16]}], [13, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [3]}], [13, 20, {"cores": 17, "ethernet": [8, 16]}], [13, 21, {"cores": 17, "ethernet": [8, 16]}], [13, 22, {"cores": 17, "ethernet": [8, 16]}], [13, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [13, 29, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [13, 30, {"cores": 17, "ethernet": [8, 28]}], [13, 31, {"cores": 17, "ethernet": [8, 28]}], [13, 32, {"cores": 17, "ethernet": [8, 28]}], [13, 33, {"cores": 17, "ethernet": [8, 28]}], [13, 34, {"cores": 17, "ethernet": [8, 28]}], [13, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [14, 6, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [14, 7, {"cores": 17, "ethernet": [8, 4]}], [14, 8, {"cores": 17, "ethernet": [8, 4]}], [14, 9, {"cores": 17, "ethernet": [8, 4]}], [14, 10, {"cores": 17, "ethernet": [8, 4]}], [14, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [14, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [14, 19, {"cores": 17, "ethernet": [8, 16]}], [14, 20, {"cores": 17, "ethernet": [8, 16]}], [14, 21, {"cores": 17, "ethernet": [8, 16]}], [14, 22, {"cores": 17, "ethernet": [8, 16]}], [14, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [14, 30, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [14, 31, {"cores": 17, "ethernet": [8, 28]}], [14, 32, {"cores": 17, "ethernet": [8, 28]}], [14, 33, {"cores": 17, "ethernet": [8, 28]}], [14, 34, {"cores": 17, "ethernet": [8, 28]}], [14, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [15, 7, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 5]}], [15, 8, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 9, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 10, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 2]}], [15, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 5]}], [15, 20, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 21, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 22, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 2]}], [15, 31, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 5]}], [15, 32, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 33, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 34, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 40, "width": 16, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "10.11.197.9"}], [0, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [0, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.25"}], [0, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3, 4]}], [0, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.9"}], [0, 25, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 26, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 27, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [1, 4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0]}], [1, 2, {"cores": 17, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [1, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [1, 13, {"cores": 17, "ethernet": [0, 12]}], [1, 14, {"cores": 17, "ethernet": [0, 12]}], [1, 15, {"cores": 17, "ethernet": [0, 12]}], [1, 16, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [1, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [1, 25, {"cores": 17, "ethernet": [0, 24]}], [1, 26, {"cores": 17, "ethernet": [0, 24]}], [1, 27, {"cores": 17, "ethernet": [0, 24]}], [1, 28, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [2, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 4, 5]}], [2, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [5]}], [2, 3, {"cores": 17, "ethernet": [0, 0]}], [2, 4, {"cores": 17, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [2, 13, {"cores": 17, "ethernet": [0, 12]}], [2, 14, {"cores": 17, "ethernet": [0, 12]}], [2, 15, {"cores": 17, "ethernet": [0, 12]}], [2, 16, {"cores": 17, "ethernet": [0, 12]}], [2, 17, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [2, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [2, 25, {"cores": 17, "ethernet": [0, 24]}], [2, 26, {"cores": 17, "ethernet": [0, 24]}], [2, 27, {"cores": 17, "ethernet": [0, 24]}], [2, 28, {"cores": 17, "ethernet": [0, 24]}], [2, 29, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [3, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [3, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4]}], [3, 3, {"cores": 16, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [3, 13, {"cores": 17, "ethernet": [0, 12]}], [3, 14, {"cores": 17, "ethernet": [0, 12]}], [3, 15, {"cores": 17, "ethernet": [0, 12]}], [3, 16, {"cores": 17, "ethernet": [0, 12]}], [3, 17, {"cores": 17, "ethernet": [0, 12]}], [3, 18, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [3, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [3, 25, {"cores": 17, "ethernet": [0, 24]}], [3, 26, {"cores": 17, "ethernet": [0, 24]}], [3, 27, {"cores": 17, "ethernet": [0, 24]}], [3, 28, {"cores": 17, "ethernet": [0, 24]}], [3, 29, {"cores": 17, "ethernet": [0, 24]}], [3, 30, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [4, 0, {"cores": 16, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 17, "ethernet": [0, 0]}], [4, 2, {"cores": 17, "ethernet": [0, 0]}], [4, 3, {"cores": 17, "ethernet": [0, 0]}], [4, 4, {"cores": 17, "ethernet": [0, 0]}], [4, 5, {"cores": 17, "ethernet": [0, 0]}], [4, 6, {"cores": 17, "ethernet": [0, 0]}], [4, 7, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [4, 8, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4], "ipAddress": "10.11.197.73"}], [4, 9, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 10, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [4, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [1]}], [4, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [0]}], [4, 15, {"cores": 17, "ethernet": [0, 12]}], [4, 16, {"cores": 17, "ethernet": [0, 12]}], [4, 17, {"cores": 17, "ethernet": [0, 12]}], [4, 18, {"cores": 17, "ethernet": [0, 12]}], [4, 19, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [4, 20, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4], "ipAddress": "10.11.196.89"}], [4, 21, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4]}], [4, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1, 3, 4]}], [4, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 3, 4]}], [4, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4]}], [4, 25, {"cores": 17, "ethernet": [0, 24]}], [4, 26, {"cores": 17, "ethernet": [0, 24]}], [4, 27, {"cores": 17, "ethernet": [0, 24]}], [4, 28, {"cores": 17, "ethernet": [0, 24]}], [4, 29, {"cores": 17, "ethernet": [0, 24]}], [4, 30, {"cores": 17, "ethernet": [0, 24]}], [4, 31, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3]}], [4, 32, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4], "ipAddress": "10.11.196.73"}], [4, 33, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 34, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3, 4]}], [5, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 17, "ethernet": [0, 0]}], [5, 4, {"cores": 16, "ethernet": [0, 0]}], [5, 5, {"cores": 17, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 17, "ethernet": [0, 0]}], [5, 8, {"cores": 17, "ethernet": [4, 8]}], [5, 9, {"cores": 17, "ethernet": [4, 8]}], [5, 10, {"cores": 17, "ethernet": [4, 8]}], [5, 11, {"cores": 17, "ethernet": [4, 8]}], [5, 12, {"cores": 17, "ethernet": [4, 8]}], [5, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2]}], [5, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [5]}], [5, 16, {"cores": 17, "ethernet": [0, 12]}], [5, 17, {"cores": 17, "ethernet": [0, 12]}], [5, 18, {"cores": 17, "ethernet": [0, 12]}], [5, 19, {"cores": 17, "ethernet": [0, 12]}], [5, 20, {"cores": 17, "ethernet": [4, 20]}], [5, 21, {"cores": 17, "ethernet": [4, 20]}], [5, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [2]}], [5, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [5]}], [5, 25, {"cores": 17, "ethernet": [0, 24]}], [5, 26, {"cores": 17, "ethernet": [0, 24]}], [5, 27, {"cores": 17, "ethernet": [0, 24]}], [5, 28, {"cores": 17, "ethernet": [0, 24]}], [5, 29, {"cores": 17, "ethernet": [0, 24]}], [5, 30, {"cores": 17, "ethernet": [0, 24]}], [5, 31, {"cores": 17, "ethernet": [0, 24]}], [5, 32, {"cores": 17, "ethernet": [4, 32]}], [5, 33, {"cores": 17, "ethernet": [4, 32]}], [5, 34, {"cores": 17, "ethernet": [4, 32]}], [5, 35, {"cores": 17, "ethernet": [4, 32]}], [5, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [6, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 17, "ethernet": [0, 0]}], [6, 5, {"cores": 17, "ethernet": [0, 0]}], [6, 6, {"cores": 17, "ethernet": [0, 0]}], [6, 7, {"cores": 17, "ethernet": [0, 0]}], [6, 8, {"cores": 17, "ethernet": [4, 8]}], [6, 9, {"cores": 17, "ethernet": [4, 8]}], [6, 10, {"cores": 17, "ethernet": [4, 8]}], [6, 11, {"cores": 17, "ethernet": [4, 8]}], [6, 12, {"cores": 17, "ethernet": [4, 8]}], [6, 13, {"cores": 17, "ethernet": [4, 8]}], [6, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [6, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [6, 16, {"cores": 17, "ethernet": [0, 12]}], [6, 17, {"cores": 17, "ethernet": [0, 12]}], [6, 18, {"cores": 17, "ethernet": [0, 12]}], [6, 19, {"cores": 17, "ethernet": [0, 12]}], [6, 20, {"cores": 17, "ethernet": [4, 20]}], [6, 21, {"cores": 17, "ethernet": [4, 20]}], [6, 22, {"cores": 17, "ethernet": [4, 20]}], [6, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3]}], [6, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [4]}], [6, 25, {"cores": 17, "ethernet": [4, 20]}], [6, 26, {"cores": 17, "ethernet": [0, 24]}], [6, 27, {"cores": 17, "ethernet": [0, 24]}], [6, 28, {"cores": 17, "ethernet": [0, 24]}], [6, 29, {"cores": 17, "ethernet": [0, 24]}], [6, 30, {"cores": 17, "ethernet": [0, 24]}], [6, 31, {"cores": 17, "ethernet": [0, 24]}], [6, 32, {"cores": 17, "ethernet": [4, 32]}], [6, 33, {"cores": 17, "ethernet": [4, 32]}], [6, 34, {"cores": 17, "ethernet": [4, 32]}], [6, 35, {"cores": 17, "ethernet": [4, 32]}], [6, 36, {"cores": 17, "ethernet": [4, 32]}], [6, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [7, 4, {"cores": 17, "ethernet": [0, 0]}], [7, 5, {"cores": 17, "ethernet": [0, 0]}], [7, 6, {"cores": 17, "ethernet": [0, 0]}], [7, 7, {"cores": 17, "ethernet": [0, 0]}], [7, 8, {"cores": 17, "ethernet": [4, 8]}], [7, 9, {"cores": 17, "ethernet": [4, 8]}], [7, 10, {"cores": 17, "ethernet": [4, 8]}], [7, 11, {"cores": 17, "ethernet": [4, 8]}], [7, 12, {"cores": 17, "ethernet": [4, 8]}], [7, 13, {"cores": 17, "ethernet": [4, 8]}], [7, 14, {"cores": 17, "ethernet": [4, 8]}], [7, 15, {"cores": 17, "ethernet": [0, 12]}], [7, 16, {"cores": 17, "ethernet": [0, 12]}], [7, 17, {"cores": 17, "ethernet": [0, 12]}], [7, 18, {"cores": 17, "ethernet": [0, 12]}], [7, 19, {"cores": 17, "ethernet": [0, 12]}], [7, 20, {"cores": 17, "ethernet": [4, 20]}], [7, 21, {"cores": 17, "ethernet": [4, 20]}], [7, 22, {"cores": 17, "ethernet": [4, 20]}], [7, 23, {"cores": 17, "ethernet": [4, 20]}], [7, 24, {"cores": 17, "ethernet": [4, 20]}], [7, 25, {"cores": 17, "ethernet": [4, 20]}], [7, 26, {"cores": 17, "ethernet": [4, 20]}], [7, 27, {"cores": 17, "ethernet": [0, 24]}], [7, 28, {"cores": 17, "ethernet": [0, 24]}], [7, 29, {"cores": 17, "ethernet": [0, 24]}], [7, 30, {"cores": 17, "ethernet": [0, 24]}], [7, 31, {"cores": 17, "ethernet": [0, 24]}], [7, 32, {"cores": 17, "ethernet": [4, 32]}], [7, 33, {"cores": 17, "ethernet": [4, 32]}], [7, 34, {"cores": 17, "ethernet": [4, 32]}], [7, 35, {"cores": 17, "ethernet": [4, 32]}], [7, 36, {"cores": 17, "ethernet": [4, 32]}], [7, 37, {"cores": 17, "ethernet": [4, 32]}], [7, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [8, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [5], "ipAddress": "10.11.197.137"}], [8, 5, {"cores": 17, "ethernet": [8, 4]}], [8, 6, {"cores": 17, "ethernet": [8, 4]}], [8, 7, {"cores": 17, "ethernet": [8, 4]}], [8, 8, {"cores": 17, "ethernet": [4, 8]}], [8, 9, {"cores": 17, "ethernet": [4, 8]}], [8, 10, {"cores": 17, "ethernet": [4, 8]}], [8, 11, {"cores": 17, "ethernet": [4, 8]}], [8, 12, {"cores": 17, "ethernet": [4, 8]}], [8, 13, {"cores": 17, "ethernet": [4, 8]}], [8, 14, {"cores": 17, "ethernet": [4, 8]}], [8, 15, {"cores": 17, "ethernet": [4, 8]}], [8, 16, {"cores": 17, "ethernet": [8, 16], "ipAddress": "10.11.196.153"}], [8, 17, {"cores": 17, "ethernet": [8, 16]}], [8, 18, {"cores": 17, "ethernet": [8, 16]}], [8, 19, {"cores": 17, "ethernet": [8, 16]}], [8, 20, {"cores": 17, "ethernet": [4, 20]}], [8, 21, {"cores": 17, "ethernet": [4, 20]}], [8, 22, {"cores": 17, "ethernet": [4, 20]}], [8, 23, {"cores": 17, "ethernet": [4, 20]}], [8, 24, {"cores": 17, "ethernet": [4, 20]}], [8, 25, {"cores": 17, "ethernet": [4, 20]}], [8, 26, {"cores": 17, "ethernet": [4, 20]}], [8, 27, {"cores": 17, "ethernet": [4, 20]}], [8, 28, {"cores": 17, "ethernet": [8, 28], "ipAddress": "10.11.196.137"}], [8, 29, {"cores": 17, "ethernet": [8, 28]}], [8, 30, {"cores": 17, "ethernet": [8, 28]}], [8, 31, {"cores": 17, "ethernet": [8, 28]}], [8, 32, {"cores": 17, "ethernet": [4, 32]}], [8, 33, {"cores": 17, "ethernet": [4, 32]}], [8, 34, {"cores": 17, "ethernet": [4, 32]}], [8, 35, {"cores": 17, "ethernet": [4, 32]}], [8, 36, {"cores": 17, "ethernet": [4, 32]}], [8, 37, {"cores": 17, "ethernet": [4, 32]}], [8, 38, {"cores": 17, "ethernet": [4, 32]}], [8, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2, 3]}], [9, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [9, 5, {"cores": 17, "ethernet": [8, 4]}], [9, 6, {"cores": 17, "ethernet": [8, 4]}], [9, 7, {"cores": 17, "ethernet": [8, 4]}], [9, 8, {"cores": 17, "ethernet": [8, 4]}], [9, 9, {"cores": 17, "ethernet": [4, 8]}], [9, 10, {"cores": 17, "ethernet": [4, 8]}], [9, 11, {"cores": 17, "ethernet": [4, 8]}], [9, 12, {"cores": 17, "ethernet": [4, 8]}], [9, 13, {"cores": 17, "ethernet": [4, 8]}], [9, 14, {"cores": 17, "ethernet": [4, 8]}], [9, 15, {"cores": 17, "ethernet": [4, 8]}], [9, 16, {"cores": 17, "ethernet": [8, 16]}], [9, 17, {"cores": 17, "ethernet": [8, 16]}], [9, 18, {"cores": 17, "ethernet": [8, 16]}], [9, 19, {"cores": 17, "ethernet": [8, 16]}], [9, 20, {"cores": 17, "ethernet": [8, 16]}], [9, 21, {"cores": 17, "ethernet": [4, 20]}], [9, 22, {"cores": 17, "ethernet": [4, 20]}], [9, 23, {"cores": 17, "ethernet": [4, 20]}], [9, 24, {"cores": 17, "ethernet": [4, 20]}], [9, 25, {"cores": 17, "ethernet": [4, 20]}], [9, 26, {"cores": 17, "ethernet": [4, 20]}], [9, 27, {"cores": 17, "ethernet": [4, 20]}], [9, 28, {"cores": 17, "ethernet": [8, 28]}], [9, 29, {"cores": 17, "ethernet": [8, 28]}], [9, 30, {"cores": 17, "ethernet": [8, 28]}], [9, 31, {"cores": 17, "ethernet": [8, 28]}], [9, 32, {"cores": 17, "ethernet": [8, 28]}], [9, 33, {"cores": 17, "ethernet": [4, 32]}], [9, 34, {"cores": 17, "ethernet": [4, 32]}], [9, 35, {"cores": 17, "ethernet": [4, 32]}], [9, 36, {"cores": 17, "ethernet": [4, 32]}], [9, 37, {"cores": 17, "ethernet": [4, 32]}], [9, 38, {"cores": 15, "ethernet": [4, 32]}], [9, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [10, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [10, 5, {"cores": 17, "ethernet": [8, 4]}], [10, 6, {"cores": 17, "ethernet": [8, 4]}], [10, 7, {"cores": 17, "ethernet": [8, 4]}], [10, 8, {"cores": 17, "ethernet": [8, 4]}], [10, 9, {"cores": 17, "ethernet": [8, 4]}], [10, 10, {"cores": 17, "ethernet": [4, 8]}], [10, 11, {"cores": 17, "ethernet": [4, 8]}], [10, 12, {"cores": 17, "ethernet": [4, 8]}], [10, 13, {"cores": 17, "ethernet": [4, 8]}], [10, 14, {"cores": 17, "ethernet": [4, 8]}], [10, 15, {"cores": 17, "ethernet": [4, 8]}], [10, 16, {"cores": 17, "ethernet": [8, 16]}], [10, 17, {"cores": 17, "ethernet": [8, 16]}], [10, 18, {"cores": 17, "ethernet": [8, 16]}], [10, 19, {"cores": 17, "ethernet": [8, 16]}], [10, 20, {"cores": 17, "ethernet": [8, 16]}], [10, 21, {"cores": 17, "ethernet": [8, 16]}], [10, 22, {"cores": 17, "ethernet": [4, 20]}], [10, 23, {"cores": 17, "ethernet": [4, 20]}], [10, 24, {"cores": 17, "ethernet": [4, 20]}], [10, 25, {"cores": 17, "ethernet": [4, 20]}], [10, 26, {"cores": 17, "ethernet": [4, 20]}], [10, 27, {"cores": 17, "ethernet": [4, 20]}], [10, 28, {"cores": 17, "ethernet": [8, 28]}], [10, 29, {"cores": 17, "ethernet": [8, 28]}], [10, 30, {"cores": 17, "ethernet": [8, 28]}], [10, 31, {"cores": 17, "ethernet": [8, 28]}], [10, 32, {"cores": 17, "ethernet": [8, 28]}], [10, 33, {"cores": 17, "ethernet": [8, 28]}], [10, 34, {"cores": 17, "ethernet": [4, 32]}], [10, 35, {"cores": 17, "ethernet": [4, 32]}], [10, 36, {"cores": 17, "ethernet": [4, 32]}], [10, 37, {"cores": 17, "ethernet": [4, 32]}], [10, 38, {"cores": 17, "ethernet": [4, 32]}], [10, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [11, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [11, 5, {"cores": 17, "ethernet": [8, 4]}], [11, 6, {"cores": 17, "ethernet": [8, 4]}], [11, 7, {"cores": 17, "ethernet": [8, 4]}], [11, 8, {"cores": 17, "ethernet": [8, 4]}], [11, 9, {"cores": 17, "ethernet": [8, 4]}], [11, 10, {"cores": 17, "ethernet": [8, 4]}], [11, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [1]}], [11, 12, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 13, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 14, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 15, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0]}], [11, 16, {"cores": 17, "ethernet": [8, 16]}], [11, 17, {"cores": 17, "ethernet": [8, 16]}], [11, 18, {"cores": 17, "ethernet": [8, 16]}], [11, 19, {"cores": 17, "ethernet": [8, 16]}], [11, 20, {"cores": 17, "ethernet": [8, 16]}], [11, 21, {"cores": 17, "ethernet": [8, 16]}], [11, 22, {"cores": 17, "ethernet": [8, 16]}], [11, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1]}], [11, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 25, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 26, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 27, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0]}], [11, 28, {"cores": 17, "ethernet": [8, 28]}], [11, 29, {"cores": 17, "ethernet": [8, 28]}], [11, 30, {"cores": 17, "ethernet": [8, 28]}], [11, 31, {"cores": 17, "ethernet": [8, 28]}], [11, 32, {"cores": 17, "ethernet": [8, 28]}], [11, 33, {"cores": 17, "ethernet": [8, 28]}], [11, 34, {"cores": 17, "ethernet": [8, 28]}], [11, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1]}], [11, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1, 2]}], [12, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 4, 5]}], [12, 5, {"cores": 17, "ethernet": [8, 4]}], [12, 6, {"cores": 17, "ethernet": [8, 4]}], [12, 7, {"cores": 17, "ethernet": [8, 4]}], [12, 8, {"cores": 17, "ethernet": [8, 4]}], [12, 9, {"cores": 17, "ethernet": [8, 4]}], [12, 10, {"cores": 17, "ethernet": [8, 4]}], [12, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [12, 16, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 17, {"cores": 17, "ethernet": [8, 16]}], [12, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [2]}], [12, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 20, {"cores": 17, "ethernet": [8, 16]}], [12, 21, {"cores": 17, "ethernet": [8, 16]}], [12, 22, {"cores": 17, "ethernet": [8, 16]}], [12, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [12, 28, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [12, 29, {"cores": 17, "ethernet": [8, 28]}], [12, 30, {"cores": 17, "ethernet": [8, 28]}], [12, 31, {"cores": 17, "ethernet": [8, 28]}], [12, 32, {"cores": 17, "ethernet": [8, 28]}], [12, 33, {"cores": 17, "ethernet": [8, 28]}], [12, 34, {"cores": 17, "ethernet": [8, 28]}], [12, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [13, 5, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [13, 6, {"cores": 17, "ethernet": [8, 4]}], [13, 7, {"cores": 17, "ethernet": [8, 4]}], [13, 8, {"cores": 17, "ethernet": [8, 4]}], [13, 9, {"cores": 17, "ethernet": [8, 4]}], [13, 10, {"cores": 17, "ethernet": [8, 4]}], [13, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [13, 17, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [13, 18, {"cores": 17, "ethernet": [8, 16]}], [13, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [3]}], [13, 20, {"cores": 17, "ethernet": [8, 16]}], [13, 21, {"cores": 17, "ethernet": [8, 16]}], [13, 22, {"cores": 17, "ethernet": [8, 16]}], [13, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [13, 29, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [13, 30, {"cores": 17, "ethernet": [8, 28]}], [13, 31, {"cores": 17, "ethernet": [8, 28]}], [13, 32, {"cores": 17, "ethernet": [8, 28]}], [13, 33, {"cores": 17, "ethernet": [8, 28]}], [13, 34, {"cores": 17, "ethernet": [8, 28]}], [13, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [14, 6, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [14, 7, {"cores": 17, "ethernet": [8, 4]}], [14, 8, {"cores": 17, "ethernet": [8, 4]}], [14, 9, {"cores": 17, "ethernet": [8, 4]}], [14, 10, {"cores": 17, "ethernet": [8, 4]}], [14, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [14, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [14, 19, {"cores": 17, "ethernet": [8, 16]}], [14, 20, {"cores": 17, "ethernet": [8, 16]}], [14, 21, {"cores": 17, "ethernet": [8, 16]}], [14, 22, {"cores": 17, "ethernet": [8, 16]}], [14, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [14, 30, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [14, 31, {"cores": 17, "ethernet": [8, 28]}], [14, 32, {"cores": 17, "ethernet": [8, 28]}], [14, 33, {"cores": 17, "ethernet": [8, 28]}], [14, 34, {"cores": 17, "ethernet": [8, 28]}], [14, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [15, 7, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 5]}], [15, 8, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 9, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 10, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 2]}], [15, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 5]}], [15, 20, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 21, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 22, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 2]}], [15, 31, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 5]}], [15, 32, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 33, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 34, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn2.json b/SpiNNaker-machine/src/test/resources/spinn2.json index 89e2f8bd6d..e2be180d63 100644 --- a/SpiNNaker-machine/src/test/resources/spinn2.json +++ b/SpiNNaker-machine/src/test/resources/spinn2.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn4.json b/SpiNNaker-machine/src/test/resources/spinn4.json index 0174e20a48..9c8b1a635c 100644 --- a/SpiNNaker-machine/src/test/resources/spinn4.json +++ b/SpiNNaker-machine/src/test/resources/spinn4.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json b/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json index be59185215..2fe28e5652 100644 --- a/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json +++ b/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 117}, {"monitors": 2, "routerEntries": 2147483647, "sdram": 123469692}], [1, 2, {"cores": 18, "ethernet": [0, 0]}, {"monitors": 3, "sdram": 123469691}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 117}, {"monitors": 2, "routerEntries": 2147483647, "sdram": 123469692}], [1, 2, {"cores": 18, "ethernet": [0, 0]}, {"monitors": 3, "sdram": 123469691}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/test24_12.json b/SpiNNaker-machine/src/test/resources/test24_12.json index f15f52d6ca..7b496e9aac 100644 --- a/SpiNNaker-machine/src/test/resources/test24_12.json +++ b/SpiNNaker-machine/src/test/resources/test24_12.json @@ -49,4 +49,4 @@ [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], - [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file + [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-pacman/src/test/java/.gitignore b/SpiNNaker-pacman/src/test/java/.gitignore index e69de29bb2..8b13789179 100644 --- a/SpiNNaker-pacman/src/test/java/.gitignore +++ b/SpiNNaker-pacman/src/test/java/.gitignore @@ -0,0 +1 @@ + diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java index 34177bb06f..b4af2ba85d 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java @@ -1,81 +1,81 @@ -/* - * 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 - * - * http://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.py2json; - -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toList; - -import java.util.List; - -import org.python.core.PyObject; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.Positive; -import jakarta.validation.constraints.PositiveOrZero; -import uk.ac.manchester.spinnaker.utils.validation.IPAddress; -import uk.ac.manchester.spinnaker.utils.validation.TCPPort; - -/** A configuration description. JSON-serializable. */ -public final class Configuration { - /** The machines to manage. */ - @NotEmpty(message = "there must be at least one machine described") - public final List<@Valid Machine> machines; - - /** The port for the service to listen on. */ - @TCPPort - public final int port; - - /** - * The host address for the service to listen on. Empty = all interfaces. - */ - @IPAddress(emptyOK = true) - public final String ip; - - /** How often (in seconds) to check for timeouts. */ - @Positive - public final double timeoutCheckInterval; - - /** How many retired jobs to retain. */ - @PositiveOrZero - public final int maxRetiredJobs; - - /** Time to wait before freeing. */ - @PositiveOrZero - public final int secondsBeforeFree; - - Configuration(PyObject configuration) { - machines = toList(getattr(configuration, "machines"), Machine::new); - port = getattr(configuration, "port").asInt(); - ip = getattr(configuration, "ip").asString(); - timeoutCheckInterval = - getattr(configuration, "timeout_check_interval").asDouble(); - maxRetiredJobs = getattr(configuration, "max_retired_jobs").asInt(); - secondsBeforeFree = - getattr(configuration, "seconds_before_free").asInt(); - } - - @Override - public String toString() { - return new StringBuilder("Configuration(").append("machines=") - .append(machines).append(",").append("port=").append(port) - .append(",").append("ip=").append(ip).append(",") - .append("timeoutCheckInterval=").append(timeoutCheckInterval) - .append(",").append("maxRetiredJobs=").append(maxRetiredJobs) - .append(",").append("secondsBeforeFree=") - .append(secondsBeforeFree).append(")").toString(); - } -} +/* + * 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 + * + * http://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.py2json; + +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toList; + +import java.util.List; + +import org.python.core.PyObject; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; +import uk.ac.manchester.spinnaker.utils.validation.IPAddress; +import uk.ac.manchester.spinnaker.utils.validation.TCPPort; + +/** A configuration description. JSON-serializable. */ +public final class Configuration { + /** The machines to manage. */ + @NotEmpty(message = "there must be at least one machine described") + public final List<@Valid Machine> machines; + + /** The port for the service to listen on. */ + @TCPPort + public final int port; + + /** + * The host address for the service to listen on. Empty = all interfaces. + */ + @IPAddress(emptyOK = true) + public final String ip; + + /** How often (in seconds) to check for timeouts. */ + @Positive + public final double timeoutCheckInterval; + + /** How many retired jobs to retain. */ + @PositiveOrZero + public final int maxRetiredJobs; + + /** Time to wait before freeing. */ + @PositiveOrZero + public final int secondsBeforeFree; + + Configuration(PyObject configuration) { + machines = toList(getattr(configuration, "machines"), Machine::new); + port = getattr(configuration, "port").asInt(); + ip = getattr(configuration, "ip").asString(); + timeoutCheckInterval = + getattr(configuration, "timeout_check_interval").asDouble(); + maxRetiredJobs = getattr(configuration, "max_retired_jobs").asInt(); + secondsBeforeFree = + getattr(configuration, "seconds_before_free").asInt(); + } + + @Override + public String toString() { + return new StringBuilder("Configuration(").append("machines=") + .append(machines).append(",").append("port=").append(port) + .append(",").append("ip=").append(ip).append(",") + .append("timeoutCheckInterval=").append(timeoutCheckInterval) + .append(",").append("maxRetiredJobs=").append(maxRetiredJobs) + .append(",").append("secondsBeforeFree=") + .append(secondsBeforeFree).append(")").toString(); + } +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java index 60ccc93037..193a014cc6 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java @@ -1,43 +1,43 @@ -/* - * 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 - * - * http://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.py2json; - -/** - * Enumeration of links from a SpiNNaker chip. - *

- * Note that the numbers chosen have two useful properties: - * - *

    - *
  • The integer values assigned are chosen to match the numbers used to - * identify the links in the low-level software API and hardware registers. - *
  • The links are ordered consecutively in anticlockwise order meaning the - * opposite link is {@code (link+3)%6}. - *
- */ -public enum Link { - /** East. */ - east, - /** North-East. */ - northEast, - /** North. */ - north, - /** West. */ - west, - /** South-West. */ - southWest, - /** South. */ - south -} +/* + * 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 + * + * http://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.py2json; + +/** + * Enumeration of links from a SpiNNaker chip. + *

+ * Note that the numbers chosen have two useful properties: + * + *

    + *
  • The integer values assigned are chosen to match the numbers used to + * identify the links in the low-level software API and hardware registers. + *
  • The links are ordered consecutively in anticlockwise order meaning the + * opposite link is {@code (link+3)%6}. + *
+ */ +public enum Link { + /** East. */ + east, + /** North-East. */ + northEast, + /** North. */ + north, + /** West. */ + west, + /** South-West. */ + southWest, + /** South. */ + south +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java index 82af0a8312..7effc99391 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java @@ -1,176 +1,176 @@ -/* - * 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 - * - * http://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.py2json; - -import static java.util.Collections.disjoint; -import static java.util.EnumSet.noneOf; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.item; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toCollectingMap; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toMap; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toSet; - -import java.util.EnumSet; -import java.util.Map; -import java.util.Set; - -import org.python.core.PyObject; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.errorprone.annotations.Keep; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import uk.ac.manchester.spinnaker.machine.board.BMPCoords; -import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; -import uk.ac.manchester.spinnaker.machine.board.TriadCoords; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadHeight; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth; -import uk.ac.manchester.spinnaker.utils.validation.IPAddress; - -/** A machine description. JSON-serializable. */ -public final class Machine { - /** The name of the machine. */ - @NotBlank - public final String name; - - /** The tags of the machine. */ - @NotEmpty - public final Set<@NotBlank String> tags; - - /** The width of the machine, in triads. */ - @ValidTriadWidth - public final int width; - - /** The height of the machine, in triads. */ - @ValidTriadHeight - public final int height; - - /** The dead boards of the machine. */ - public final Set<@Valid TriadCoords> deadBoards; - - /** - * The extra dead links of the machine. Doesn't include links to dead - * boards. - */ - @NotNull - public final Map<@Valid TriadCoords, @NotEmpty EnumSet> deadLinks; - - /** The logical-to-physical board location map. */ - @NotNull - public final Map<@Valid TriadCoords, @Valid PhysicalCoords> boardLocations; - - /** The IP addresses of the BMPs. */ - @JsonProperty("bmp-ips") - @NotNull - public final Map<@Valid BMPCoords, @IPAddress String> bmpIPs; - - /** The IP addresses of the boards. */ - @JsonProperty("spinnaker-ips") - @NotNull - public final Map<@Valid TriadCoords, @IPAddress String> spinnakerIPs; - - private static final int IDX = 3; - - Machine(PyObject machine) { - name = getattr(machine, "name").asString(); - tags = toSet(getattr(machine, "tags"), PyObject::asString); - width = getattr(machine, "width").asInt(); - height = getattr(machine, "height").asInt(); - deadBoards = toSet(getattr(machine, "dead_boards"), Machine::xyz); - deadLinks = toCollectingMap(getattr(machine, "dead_links"), - Machine::xyz, () -> noneOf(Link.class), - key -> Link.values()[item(key, IDX).asInt()]); - boardLocations = toMap(getattr(machine, "board_locations"), - Machine::xyz, Machine::cfb); - bmpIPs = toMap(getattr(machine, "bmp_ips"), Machine::cf, - PyObject::asString); - spinnakerIPs = toMap(getattr(machine, "spinnaker_ips"), Machine::xyz, - PyObject::asString); - } - - private static TriadCoords xyz(PyObject tuple) { - int index = 0; - int x = item(tuple, index++).asInt(); - int y = item(tuple, index++).asInt(); - int z = item(tuple, index++).asInt(); - return new TriadCoords(x, y, z); - } - - private static PhysicalCoords cfb(PyObject tuple) { - int index = 0; - int c = item(tuple, index++).asInt(); - int f = item(tuple, index++).asInt(); - int b = item(tuple, index++).asInt(); - return new PhysicalCoords(c, f, b); - } - - private static BMPCoords cf(PyObject tuple) { - int index = 0; - int c = item(tuple, index++).asInt(); - int f = item(tuple, index++).asInt(); - return new BMPCoords(c, f); - } - - @Override - public String toString() { - return new StringBuilder("Machine(").append("name=").append(name) - .append(",").append("tags=").append(tags).append(",") - .append("width=").append(width).append(",").append("height=") - .append(height).append(",").append("deadBoards=") - .append(deadBoards).append(",").append("deadLinks=") - .append(deadLinks).append(",").append("boardLocations=") - .append(boardLocations).append(",").append("bmpIPs=") - .append(bmpIPs).append(",").append("spinnakerIPs=") - .append(spinnakerIPs).append(")").toString(); - } - - @Keep - @AssertTrue(message = "all boards must have a location and an IP address") - private boolean isEveryBoardWithBMPAndIPaddress() { - return boardLocations.keySet().equals(spinnakerIPs.keySet()); - } - - @Keep - @AssertTrue(message = "every board's IP address must be unique") - private boolean isEveryBoardIPAddressUnique() { - return spinnakerIPs.size() == Set.copyOf(spinnakerIPs.values()).size(); - } - - @Keep - @AssertTrue(message = "every BMP's IP address must be unique") - private boolean isEveryBmpIPAddressUnique() { - return bmpIPs.size() == Set.copyOf(bmpIPs.values()).size(); - } - - @Keep - @AssertTrue(message = "IP addresses may not be assigned to " - + "both boards and BMPs") - private boolean isBoardAddressSetDisjointFromBmpAddressSet() { - return disjoint(spinnakerIPs.values(), bmpIPs.values()); - } - - @Keep - @AssertTrue(message = "every board's BMP must be addressable") - private boolean isEveryBoardManaged() { - return boardLocations.values().stream() - .map(PhysicalCoords::getBmpCoords) - .allMatch(bmpIPs::containsKey); - } -} +/* + * 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 + * + * http://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.py2json; + +import static java.util.Collections.disjoint; +import static java.util.EnumSet.noneOf; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.item; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toCollectingMap; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toMap; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toSet; + +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; + +import org.python.core.PyObject; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.errorprone.annotations.Keep; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import uk.ac.manchester.spinnaker.machine.board.BMPCoords; +import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; +import uk.ac.manchester.spinnaker.machine.board.TriadCoords; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadHeight; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth; +import uk.ac.manchester.spinnaker.utils.validation.IPAddress; + +/** A machine description. JSON-serializable. */ +public final class Machine { + /** The name of the machine. */ + @NotBlank + public final String name; + + /** The tags of the machine. */ + @NotEmpty + public final Set<@NotBlank String> tags; + + /** The width of the machine, in triads. */ + @ValidTriadWidth + public final int width; + + /** The height of the machine, in triads. */ + @ValidTriadHeight + public final int height; + + /** The dead boards of the machine. */ + public final Set<@Valid TriadCoords> deadBoards; + + /** + * The extra dead links of the machine. Doesn't include links to dead + * boards. + */ + @NotNull + public final Map<@Valid TriadCoords, @NotEmpty EnumSet> deadLinks; + + /** The logical-to-physical board location map. */ + @NotNull + public final Map<@Valid TriadCoords, @Valid PhysicalCoords> boardLocations; + + /** The IP addresses of the BMPs. */ + @JsonProperty("bmp-ips") + @NotNull + public final Map<@Valid BMPCoords, @IPAddress String> bmpIPs; + + /** The IP addresses of the boards. */ + @JsonProperty("spinnaker-ips") + @NotNull + public final Map<@Valid TriadCoords, @IPAddress String> spinnakerIPs; + + private static final int IDX = 3; + + Machine(PyObject machine) { + name = getattr(machine, "name").asString(); + tags = toSet(getattr(machine, "tags"), PyObject::asString); + width = getattr(machine, "width").asInt(); + height = getattr(machine, "height").asInt(); + deadBoards = toSet(getattr(machine, "dead_boards"), Machine::xyz); + deadLinks = toCollectingMap(getattr(machine, "dead_links"), + Machine::xyz, () -> noneOf(Link.class), + key -> Link.values()[item(key, IDX).asInt()]); + boardLocations = toMap(getattr(machine, "board_locations"), + Machine::xyz, Machine::cfb); + bmpIPs = toMap(getattr(machine, "bmp_ips"), Machine::cf, + PyObject::asString); + spinnakerIPs = toMap(getattr(machine, "spinnaker_ips"), Machine::xyz, + PyObject::asString); + } + + private static TriadCoords xyz(PyObject tuple) { + int index = 0; + int x = item(tuple, index++).asInt(); + int y = item(tuple, index++).asInt(); + int z = item(tuple, index++).asInt(); + return new TriadCoords(x, y, z); + } + + private static PhysicalCoords cfb(PyObject tuple) { + int index = 0; + int c = item(tuple, index++).asInt(); + int f = item(tuple, index++).asInt(); + int b = item(tuple, index++).asInt(); + return new PhysicalCoords(c, f, b); + } + + private static BMPCoords cf(PyObject tuple) { + int index = 0; + int c = item(tuple, index++).asInt(); + int f = item(tuple, index++).asInt(); + return new BMPCoords(c, f); + } + + @Override + public String toString() { + return new StringBuilder("Machine(").append("name=").append(name) + .append(",").append("tags=").append(tags).append(",") + .append("width=").append(width).append(",").append("height=") + .append(height).append(",").append("deadBoards=") + .append(deadBoards).append(",").append("deadLinks=") + .append(deadLinks).append(",").append("boardLocations=") + .append(boardLocations).append(",").append("bmpIPs=") + .append(bmpIPs).append(",").append("spinnakerIPs=") + .append(spinnakerIPs).append(")").toString(); + } + + @Keep + @AssertTrue(message = "all boards must have a location and an IP address") + private boolean isEveryBoardWithBMPAndIPaddress() { + return boardLocations.keySet().equals(spinnakerIPs.keySet()); + } + + @Keep + @AssertTrue(message = "every board's IP address must be unique") + private boolean isEveryBoardIPAddressUnique() { + return spinnakerIPs.size() == Set.copyOf(spinnakerIPs.values()).size(); + } + + @Keep + @AssertTrue(message = "every BMP's IP address must be unique") + private boolean isEveryBmpIPAddressUnique() { + return bmpIPs.size() == Set.copyOf(bmpIPs.values()).size(); + } + + @Keep + @AssertTrue(message = "IP addresses may not be assigned to " + + "both boards and BMPs") + private boolean isBoardAddressSetDisjointFromBmpAddressSet() { + return disjoint(spinnakerIPs.values(), bmpIPs.values()); + } + + @Keep + @AssertTrue(message = "every board's BMP must be addressable") + private boolean isEveryBoardManaged() { + return boardLocations.values().stream() + .map(PhysicalCoords::getBmpCoords) + .allMatch(bmpIPs::containsKey); + } +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java index 1bedf9c9b1..74a8f67eb6 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java @@ -1,55 +1,55 @@ -/* - * 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 - * - * http://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.py2json; - -import static java.lang.String.format; -import static java.lang.System.getProperty; - -import org.python.util.PythonInterpreter; - -import com.google.errorprone.annotations.MustBeClosed; - -/** - * Hack for Java 11 and later, where just changing {@code user.dir} is no longer - * enough. We force the change inside Jython as that's the environment that - * cares. Outside... we shouldn't need to care. - */ -final class WithCurrentDirectory implements AutoCloseable { - private final PythonInterpreter python; - - @MustBeClosed - WithCurrentDirectory(PythonInterpreter python, boolean doCd) { - var cwd = getProperty("user.dir"); - if (doCd) { - this.python = python; - } else { - this.python = null; - } - run(format("import os; __saved=os.getcwd(); os.chdir(r'''%s''')", cwd)); - } - - private void run(String script) { - if (python == null) { - return; - } - python.exec(script); - } - - @Override - public void close() { - run("os.chdir(__saved)"); - } -} +/* + * 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 + * + * http://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.py2json; + +import static java.lang.String.format; +import static java.lang.System.getProperty; + +import org.python.util.PythonInterpreter; + +import com.google.errorprone.annotations.MustBeClosed; + +/** + * Hack for Java 11 and later, where just changing {@code user.dir} is no longer + * enough. We force the change inside Jython as that's the environment that + * cares. Outside... we shouldn't need to care. + */ +final class WithCurrentDirectory implements AutoCloseable { + private final PythonInterpreter python; + + @MustBeClosed + WithCurrentDirectory(PythonInterpreter python, boolean doCd) { + var cwd = getProperty("user.dir"); + if (doCd) { + this.python = python; + } else { + this.python = null; + } + run(format("import os; __saved=os.getcwd(); os.chdir(r'''%s''')", cwd)); + } + + private void run(String script) { + if (python == null) { + return; + } + python.exec(script); + } + + @Override + public void close() { + run("os.chdir(__saved)"); + } +} diff --git a/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py b/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py index 8de8ed6768..8030369a6a 100644 --- a/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py +++ b/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py @@ -1,41 +1,41 @@ -# 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 -# -# http://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. - -from spalloc_server.configuration import * -from spalloc_server.links import * - -m = Machine(name="my-three-board-machine", - board_locations={ - #X Y Z C F B - (0, 0, 0): (0, 0, 0), - (0, 0, 1): (0, 0, 2), - (0, 0, 2): (0, 0, 5), - }, - # Just one BMP - bmp_ips={ - #C F - (0, 0): "192.168.240.0", - }, - # Each SpiNNaker board has an IP - spinnaker_ips={ - #X Y Z - (0, 0, 0): "192.168.240.1", - (0, 0, 1): "192.168.240.17", - (0, 0, 2): "192.168.240.41", - }, - dead_links={ - #X Y Z Direction - (0, 0, 0, Links.east) - }) -configuration = Configuration(machines=[m]) +# 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 +# +# http://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. + +from spalloc_server.configuration import * +from spalloc_server.links import * + +m = Machine(name="my-three-board-machine", + board_locations={ + #X Y Z C F B + (0, 0, 0): (0, 0, 0), + (0, 0, 1): (0, 0, 2), + (0, 0, 2): (0, 0, 5), + }, + # Just one BMP + bmp_ips={ + #C F + (0, 0): "192.168.240.0", + }, + # Each SpiNNaker board has an IP + spinnaker_ips={ + #X Y Z + (0, 0, 0): "192.168.240.1", + (0, 0, 1): "192.168.240.17", + (0, 0, 2): "192.168.240.41", + }, + dead_links={ + #X Y Z Direction + (0, 0, 0, Links.east) + }) +configuration = Configuration(machines=[m]) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java index 55d878fe86..3049cc18ee 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.storage.sqlite; - -/** Ordinal numbers. Used for positional parameters in SQL statements. */ -interface Ordinals { - /** First. */ - int FIRST = 1; - - /** Second. */ - int SECOND = 2; - - /** Third. */ - int THIRD = 3; - - /** Fourth. */ - int FOURTH = 4; - - /** Fifth. */ - int FIFTH = 5; - - /** Sixth. */ - int SIXTH = 6; -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.storage.sqlite; + +/** Ordinal numbers. Used for positional parameters in SQL statements. */ +interface Ordinals { + /** First. */ + int FIRST = 1; + + /** Second. */ + int SECOND = 2; + + /** Third. */ + int THIRD = 3; + + /** Fourth. */ + int FOURTH = 4; + + /** Fifth. */ + int FIFTH = 5; + + /** Sixth. */ + int SIXTH = 6; +} diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java index 767593dafc..810b4dd6c0 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.storage.sqlite; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Objects.isNull; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.commons.io.IOUtils; - -import com.google.errorprone.annotations.MustBeClosed; - -/** - * Factoring out of correct resource loading pattern. - */ -public abstract class ResourceLoader { - private ResourceLoader() { - } - - @MustBeClosed - private static InputStream open(String name) throws FileNotFoundException { - var stream = ResourceLoader.class.getResourceAsStream(name); - if (isNull(stream)) { - throw new FileNotFoundException(name); - } - return stream; - } - - /** - * Load a text resource from the given name using this class's class loader. - * - * @param name - * The name of the resource to load. - * @return The content of the resource. - * @throws RuntimeException - * If things don't work. Shouldn't happen if build is correct. - */ - public static String loadResource(String name) { - try (var stream = open(name)) { - return IOUtils.toString(stream, UTF_8); - } catch (IOException e) { - throw new RuntimeException("failed to read resource", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.storage.sqlite; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Objects.isNull; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import com.google.errorprone.annotations.MustBeClosed; + +/** + * Factoring out of correct resource loading pattern. + */ +public abstract class ResourceLoader { + private ResourceLoader() { + } + + @MustBeClosed + private static InputStream open(String name) throws FileNotFoundException { + var stream = ResourceLoader.class.getResourceAsStream(name); + if (isNull(stream)) { + throw new FileNotFoundException(name); + } + return stream; + } + + /** + * Load a text resource from the given name using this class's class loader. + * + * @param name + * The name of the resource to load. + * @return The content of the resource. + * @throws RuntimeException + * If things don't work. Shouldn't happen if build is correct. + */ + public static String loadResource(String name) { + try (var stream = open(name)) { + return IOUtils.toString(stream, UTF_8); + } catch (IOException e) { + throw new RuntimeException("failed to read resource", e); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java index 25623f4661..6db0180af4 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java @@ -1,126 +1,126 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.Math.min; -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Iterator; - -/** Utility methods for {@link ByteBuffer}s. */ -public abstract class ByteBufferUtils { - private ByteBufferUtils() { - } - - /** - * Make a slice of a byte buffer without modifying the original buffer. - * - * @param src - * The originating buffer. - * @param from - * The offset into the originating buffer where the slice starts. - * @param len - * The length of the slice. - * @return The little-endian slice. This will be read-only if and only if - * the original buffer is read-only. - */ - public static ByteBuffer slice(ByteBuffer src, int from, int len) { - var s = src.duplicate().position(from).slice(); - return s.limit(len).order(LITTLE_ENDIAN); - } - - /** - * Make a slice of a byte buffer if it exceeds a given size. - * - * @param src - * The originating buffer. - * @param maxSize - * The maximum size of the resulting buffer. - * @return The original buffer or a little-endian slice. This will be - * read-only if and only if the original buffer is read-only. - */ - public static ByteBuffer limitSlice(ByteBuffer src, int maxSize) { - if (src.remaining() <= maxSize) { - return src; - } - return src.slice().order(LITTLE_ENDIAN).limit(maxSize); - } - - /** - * Slice up a buffer buffer into a sequence of (little-endian) byte buffers - * with a maximum size. - * - * @param src - * The buffer to slice up. - * @param chunkSize - * Max size of each chunk. Must be positive. - * @return An iterable of little-endian chunks. Only the final chunk will be - * smaller than the requested chunk size. - */ - public static MappableIterable sliceUp(ByteBuffer src, - int chunkSize) { - return () -> new Iterator<>() { - final ByteBuffer b = src.duplicate(); - - @Override - public boolean hasNext() { - return b.hasRemaining(); - } - - @Override - public ByteBuffer next() { - var s = b.slice(); - s.limit(min(chunkSize, s.limit())); - b.position(b.position() + s.limit()); - return s.order(LITTLE_ENDIAN); - } - }; - } - - /** - * Read a chunk of an input stream into a byte buffer. - * - * @param data - * Where to read from. - * @param workingBuffer - * The buffer to use. The number of bytes remaining in the buffer - * is the maximum number of bytes to read unless the - * maximum bytes remaining is smaller. - * @param maxRemaining - * The maximum number of bytes remaining in the input stream; - * bytes after that point won't be read even if they exist. - * @return A view on the buffer with the data in it (endianness undefined), - * or {@code null} if EOF or the limit is reached. - * @throws IOException - * If reading fails. - */ - public static ByteBuffer read(InputStream data, ByteBuffer workingBuffer, - int maxRemaining) throws IOException { - var tmp = workingBuffer.duplicate(); - int size = min(tmp.remaining(), maxRemaining); - if (size <= 0) { - return null; - } - size = data.read(tmp.array(), tmp.arrayOffset(), size); - if (size <= 0) { - return null; - } - return tmp.limit(size); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.Math.min; +import static java.nio.ByteOrder.LITTLE_ENDIAN; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Iterator; + +/** Utility methods for {@link ByteBuffer}s. */ +public abstract class ByteBufferUtils { + private ByteBufferUtils() { + } + + /** + * Make a slice of a byte buffer without modifying the original buffer. + * + * @param src + * The originating buffer. + * @param from + * The offset into the originating buffer where the slice starts. + * @param len + * The length of the slice. + * @return The little-endian slice. This will be read-only if and only if + * the original buffer is read-only. + */ + public static ByteBuffer slice(ByteBuffer src, int from, int len) { + var s = src.duplicate().position(from).slice(); + return s.limit(len).order(LITTLE_ENDIAN); + } + + /** + * Make a slice of a byte buffer if it exceeds a given size. + * + * @param src + * The originating buffer. + * @param maxSize + * The maximum size of the resulting buffer. + * @return The original buffer or a little-endian slice. This will be + * read-only if and only if the original buffer is read-only. + */ + public static ByteBuffer limitSlice(ByteBuffer src, int maxSize) { + if (src.remaining() <= maxSize) { + return src; + } + return src.slice().order(LITTLE_ENDIAN).limit(maxSize); + } + + /** + * Slice up a buffer buffer into a sequence of (little-endian) byte buffers + * with a maximum size. + * + * @param src + * The buffer to slice up. + * @param chunkSize + * Max size of each chunk. Must be positive. + * @return An iterable of little-endian chunks. Only the final chunk will be + * smaller than the requested chunk size. + */ + public static MappableIterable sliceUp(ByteBuffer src, + int chunkSize) { + return () -> new Iterator<>() { + final ByteBuffer b = src.duplicate(); + + @Override + public boolean hasNext() { + return b.hasRemaining(); + } + + @Override + public ByteBuffer next() { + var s = b.slice(); + s.limit(min(chunkSize, s.limit())); + b.position(b.position() + s.limit()); + return s.order(LITTLE_ENDIAN); + } + }; + } + + /** + * Read a chunk of an input stream into a byte buffer. + * + * @param data + * Where to read from. + * @param workingBuffer + * The buffer to use. The number of bytes remaining in the buffer + * is the maximum number of bytes to read unless the + * maximum bytes remaining is smaller. + * @param maxRemaining + * The maximum number of bytes remaining in the input stream; + * bytes after that point won't be read even if they exist. + * @return A view on the buffer with the data in it (endianness undefined), + * or {@code null} if EOF or the limit is reached. + * @throws IOException + * If reading fails. + */ + public static ByteBuffer read(InputStream data, ByteBuffer workingBuffer, + int maxRemaining) throws IOException { + var tmp = workingBuffer.duplicate(); + int size = min(tmp.remaining(), maxRemaining); + if (size <= 0) { + return null; + } + size = data.read(tmp.array(), tmp.arrayOffset(), size); + if (size <= 0) { + return null; + } + return tmp.limit(size); + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java index ee9a916196..257baa4a41 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java @@ -1,310 +1,310 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.Math.min; -import static java.util.Arrays.stream; -import static java.util.Collections.unmodifiableCollection; -import static java.util.Collections.unmodifiableList; -import static java.util.Collections.unmodifiableMap; -import static java.util.Collections.unmodifiableSet; -import static java.util.EnumSet.noneOf; -import static java.util.Objects.isNull; -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; -import static java.util.stream.Collectors.toUnmodifiableMap; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.IntBinaryOperator; -import java.util.function.IntFunction; -import java.util.function.Supplier; -import java.util.stream.Collector; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * Utilities for working with collections. Things that it would be nice if they - * were in Java itself, but which aren't. - * - * @author Donal Fellows - * @see MappableIterable - */ -public abstract class CollectionUtils { - private CollectionUtils() { - } - - /** - * The binary and operator ({@code &}) as a function. - */ - public static final IntBinaryOperator AND = (a, b) -> a & b; - - /** - * The binary or operator ({@code |}) as a function. - */ - public static final IntBinaryOperator OR = (a, b) -> a | b; - - /** - * Create a collector that collects to an {@link EnumSet}. - * - * @param - * The type of {@code enum} we are collecting. - * @param cls - * The class of the {@code enum} we are collecting. - * @return The collector. - */ - public static > Collector> toEnumSet( - Class cls) { - return toCollection(() -> noneOf(cls)); - } - - /** - * Generate an iterable that covers a range. Only expected to cover the - * range once. - * - * @param startAt - * What value to start at. - * @param upTo - * What value to go up to (in steps of +1) but not include. - * @return A one-shot iterable. - */ - public static Iterable range(int startAt, int upTo) { - return IntStream.range(startAt, upTo)::iterator; - } - - /** - * Generate an iterable that covers a range starting at zero and counting - * up. Only expected to cover the range once. - * - * @param upTo - * What value to go up to (in steps of +1) but not include. - * @return A one-shot iterable. - */ - public static Iterable range(int upTo) { - return IntStream.range(0, upTo)::iterator; - } - - /** - * Binary function currier. - * - * @param - * First argument type. - * @param - * Second argument type - * @param - * Return type. - * @param fn - * Binary function. - * @param arg - * First argument. - * @return Unary function based on binding the first argument to the binary - * function. - */ - public static Function curry(BiFunction fn, - T arg) { - return u -> fn.apply(arg, u); - } - - /** - * Given a list of elements, split it into batches of elements of a given - * size. The final batch might be smaller. Note that this requires - * a list because it uses the {@link List#subList(int, int)} method. - * - * @param - * The type of the elements of the input list. - * @param batchSize - * The maximum number of elements in a batch. All but the final - * batch will have this number of elements; the final batch may - * have fewer. - * @param input - * The list to be split into batches. - * @return The batched list. The collections that make up each batch will be - * unmodifiable, as will the overall collection. - */ - public static Collection> batch(int batchSize, - List input) { - return unmodifiableCollection(IntStream.range(0, - (input.size() + batchSize - 1) / batchSize) - .map(i -> i * batchSize) - .mapToObj(idx -> unmodifiableCollection( - input.subList(idx, min(input.size(), idx + batchSize)))) - .collect(toList())); - } - - /** - * Like {@link Stream#map(Function)}, but for lists/collections. - * - * @param - * The type of elements of the input list. - * @param - * The type of elements of the output list. - * @param list - * The input list. - * @param fun - * How to map an element. - * @return The output list. - */ - @UsedInJavadocOnly(Stream.class) - public static List lmap(Collection list, Function fun) { - return list.stream().map(fun).collect(toList()); - } - - /** - * Parse a comma-separated string into an unordered set of items. - * - * @param - * The type of elements of the set. - * @param str - * The string to parse. - * @param mapper - * How to get an element from a piece of string. - * @return The set of items. The set is unordered. - */ - public static Set parseCommaSeparatedSet(String str, - Function mapper) { - return stream(str.split(",")).map(mapper).collect(toSet()); - } - - /** - * Utility for making the backing maps for fast {@code enum}s. These are - * expected to be used mainly to invert the trivial mapping from an - * enumeration member to its {@code value} field, though this is not assumed - * by this code. - * - * @param - * The type of the {@code enum}. - * @param - * The type of the value to use as the map key. - * @param enumMembers - * The values in the {@code enum}, as returned by the - * {@code values()} method. - * @param valueExtractor - * How to get the value to use as the map key. - * @return Unmodifiable map from the values to the {@code enum} members. - */ - public static , K> Map makeEnumBackingMap( - E[] enumMembers, Function valueExtractor) { - return stream(enumMembers) - .collect(toUnmodifiableMap(valueExtractor, v -> v)); - } - - /** - * Makes a read-only copy of a list. - * - * @param - * The type of elements in the list. - * @param list - * The list to copy. {@code null} becomes an empty list. - * @return A read-only copy of the list. - */ - public static List copy(List list) { - // Don't copyOf; avoid nullability failures - return isNull(list) ? List.of() - : unmodifiableList(new ArrayList<>(list)); - } - - /** - * Makes a read-only copy of a set. This will preserve whatever order was in - * the input set. - * - * @param - * The type of elements in the set. - * @param set - * The set to copy. {@code null} becomes an empty set. - * @return A read-only copy of the set. - */ - public static Set copy(Set set) { - // Don't copyOf; avoid nullability failures - return isNull(set) ? Set.of() - : unmodifiableSet(new LinkedHashSet<>(set)); - } - - /** - * Makes a read-only copy of a map. This will preserve whatever order was in - * the input map. - * - * @param - * The type of keys in the map. - * @param - * The type of values in the map. - * @param map - * The map to copy. {@code null} becomes an empty map. - * @return A read-only copy of the map. - */ - public static Map copy(Map map) { - // Don't copyOf; avoid nullability failures - return isNull(map) ? Map.of() - : unmodifiableMap(new LinkedHashMap<>(map)); - } - - /** - * Create a collector that produces an array from a stream. The order of the - * elements in the array will be the inherent order of the elements in the - * stream. - * - * @param - * The type of the elements. - * @param generator - * How to make the array. Typically something like - * {@code T[]::new}. - * @return A collector. - */ - public static < - T> Collector collectToArray(IntFunction generator) { - return new Collector, T[]>() { - @Override - public Supplier> supplier() { - return ArrayList::new; - } - - @Override - public BiConsumer, T> accumulator() { - return List::add; - } - - @Override - public BinaryOperator> combiner() { - return (left, right) -> { - left.addAll(right); - return left; - }; - } - - @Override - public Function, T[]> finisher() { - // We know the size right now; use it! - // Also, we assume that the generator is non-crazy - return l -> l.toArray(generator.apply(l.size())); - } - - @Override - public Set characteristics() { - return Set.of(); - } - }; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.Math.min; +import static java.util.Arrays.stream; +import static java.util.Collections.unmodifiableCollection; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.EnumSet.noneOf; +import static java.util.Objects.isNull; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Collectors.toUnmodifiableMap; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntFunction; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +/** + * Utilities for working with collections. Things that it would be nice if they + * were in Java itself, but which aren't. + * + * @author Donal Fellows + * @see MappableIterable + */ +public abstract class CollectionUtils { + private CollectionUtils() { + } + + /** + * The binary and operator ({@code &}) as a function. + */ + public static final IntBinaryOperator AND = (a, b) -> a & b; + + /** + * The binary or operator ({@code |}) as a function. + */ + public static final IntBinaryOperator OR = (a, b) -> a | b; + + /** + * Create a collector that collects to an {@link EnumSet}. + * + * @param + * The type of {@code enum} we are collecting. + * @param cls + * The class of the {@code enum} we are collecting. + * @return The collector. + */ + public static > Collector> toEnumSet( + Class cls) { + return toCollection(() -> noneOf(cls)); + } + + /** + * Generate an iterable that covers a range. Only expected to cover the + * range once. + * + * @param startAt + * What value to start at. + * @param upTo + * What value to go up to (in steps of +1) but not include. + * @return A one-shot iterable. + */ + public static Iterable range(int startAt, int upTo) { + return IntStream.range(startAt, upTo)::iterator; + } + + /** + * Generate an iterable that covers a range starting at zero and counting + * up. Only expected to cover the range once. + * + * @param upTo + * What value to go up to (in steps of +1) but not include. + * @return A one-shot iterable. + */ + public static Iterable range(int upTo) { + return IntStream.range(0, upTo)::iterator; + } + + /** + * Binary function currier. + * + * @param + * First argument type. + * @param + * Second argument type + * @param + * Return type. + * @param fn + * Binary function. + * @param arg + * First argument. + * @return Unary function based on binding the first argument to the binary + * function. + */ + public static Function curry(BiFunction fn, + T arg) { + return u -> fn.apply(arg, u); + } + + /** + * Given a list of elements, split it into batches of elements of a given + * size. The final batch might be smaller. Note that this requires + * a list because it uses the {@link List#subList(int, int)} method. + * + * @param + * The type of the elements of the input list. + * @param batchSize + * The maximum number of elements in a batch. All but the final + * batch will have this number of elements; the final batch may + * have fewer. + * @param input + * The list to be split into batches. + * @return The batched list. The collections that make up each batch will be + * unmodifiable, as will the overall collection. + */ + public static Collection> batch(int batchSize, + List input) { + return unmodifiableCollection(IntStream.range(0, + (input.size() + batchSize - 1) / batchSize) + .map(i -> i * batchSize) + .mapToObj(idx -> unmodifiableCollection( + input.subList(idx, min(input.size(), idx + batchSize)))) + .collect(toList())); + } + + /** + * Like {@link Stream#map(Function)}, but for lists/collections. + * + * @param + * The type of elements of the input list. + * @param + * The type of elements of the output list. + * @param list + * The input list. + * @param fun + * How to map an element. + * @return The output list. + */ + @UsedInJavadocOnly(Stream.class) + public static List lmap(Collection list, Function fun) { + return list.stream().map(fun).collect(toList()); + } + + /** + * Parse a comma-separated string into an unordered set of items. + * + * @param + * The type of elements of the set. + * @param str + * The string to parse. + * @param mapper + * How to get an element from a piece of string. + * @return The set of items. The set is unordered. + */ + public static Set parseCommaSeparatedSet(String str, + Function mapper) { + return stream(str.split(",")).map(mapper).collect(toSet()); + } + + /** + * Utility for making the backing maps for fast {@code enum}s. These are + * expected to be used mainly to invert the trivial mapping from an + * enumeration member to its {@code value} field, though this is not assumed + * by this code. + * + * @param + * The type of the {@code enum}. + * @param + * The type of the value to use as the map key. + * @param enumMembers + * The values in the {@code enum}, as returned by the + * {@code values()} method. + * @param valueExtractor + * How to get the value to use as the map key. + * @return Unmodifiable map from the values to the {@code enum} members. + */ + public static , K> Map makeEnumBackingMap( + E[] enumMembers, Function valueExtractor) { + return stream(enumMembers) + .collect(toUnmodifiableMap(valueExtractor, v -> v)); + } + + /** + * Makes a read-only copy of a list. + * + * @param + * The type of elements in the list. + * @param list + * The list to copy. {@code null} becomes an empty list. + * @return A read-only copy of the list. + */ + public static List copy(List list) { + // Don't copyOf; avoid nullability failures + return isNull(list) ? List.of() + : unmodifiableList(new ArrayList<>(list)); + } + + /** + * Makes a read-only copy of a set. This will preserve whatever order was in + * the input set. + * + * @param + * The type of elements in the set. + * @param set + * The set to copy. {@code null} becomes an empty set. + * @return A read-only copy of the set. + */ + public static Set copy(Set set) { + // Don't copyOf; avoid nullability failures + return isNull(set) ? Set.of() + : unmodifiableSet(new LinkedHashSet<>(set)); + } + + /** + * Makes a read-only copy of a map. This will preserve whatever order was in + * the input map. + * + * @param + * The type of keys in the map. + * @param + * The type of values in the map. + * @param map + * The map to copy. {@code null} becomes an empty map. + * @return A read-only copy of the map. + */ + public static Map copy(Map map) { + // Don't copyOf; avoid nullability failures + return isNull(map) ? Map.of() + : unmodifiableMap(new LinkedHashMap<>(map)); + } + + /** + * Create a collector that produces an array from a stream. The order of the + * elements in the array will be the inherent order of the elements in the + * stream. + * + * @param + * The type of the elements. + * @param generator + * How to make the array. Typically something like + * {@code T[]::new}. + * @return A collector. + */ + public static < + T> Collector collectToArray(IntFunction generator) { + return new Collector, T[]>() { + @Override + public Supplier> supplier() { + return ArrayList::new; + } + + @Override + public BiConsumer, T> accumulator() { + return List::add; + } + + @Override + public BinaryOperator> combiner() { + return (left, right) -> { + left.addAll(right); + return left; + }; + } + + @Override + public Function, T[]> finisher() { + // We know the size right now; use it! + // Also, we assume that the generator is non-crazy + return l -> l.toArray(generator.apply(l.size())); + } + + @Override + public Set characteristics() { + return Set.of(); + } + }; + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java index 4583c80b51..de447f27ce 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java @@ -1,83 +1,83 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.utils; - -import static java.util.Objects.requireNonNull; - -/** - * A thread that is a daemon by default. - * - * @author Donal Fellows - */ -public class Daemon extends Thread { - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - */ - public Daemon(Runnable target) { - super(requireNonNull(target)); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - * @param name - * the name of the new thread - */ - public Daemon(Runnable target, String name) { - super(requireNonNull(target), name); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param group - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. - * @param target - * the object whose {@code run} method is invoked when this - * thread is started. Never {@code null}. - */ - public Daemon(ThreadGroup group, Runnable target) { - super(group, requireNonNull(target)); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param group - * the thread group. If {@code null}, the group is set to the - * current thread's thread group. - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - * @param name - * the name of the new thread - */ - public Daemon(ThreadGroup group, Runnable target, String name) { - super(group, requireNonNull(target), name); - setDaemon(true); - } -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.utils; + +import static java.util.Objects.requireNonNull; + +/** + * A thread that is a daemon by default. + * + * @author Donal Fellows + */ +public class Daemon extends Thread { + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + */ + public Daemon(Runnable target) { + super(requireNonNull(target)); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + * @param name + * the name of the new thread + */ + public Daemon(Runnable target, String name) { + super(requireNonNull(target), name); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param group + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. + * @param target + * the object whose {@code run} method is invoked when this + * thread is started. Never {@code null}. + */ + public Daemon(ThreadGroup group, Runnable target) { + super(group, requireNonNull(target)); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param group + * the thread group. If {@code null}, the group is set to the + * current thread's thread group. + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + * @param name + * the name of the new thread + */ + public Daemon(ThreadGroup group, Runnable target, String name) { + super(group, requireNonNull(target), name); + setDaemon(true); + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java index b1f167ab87..09249313c8 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -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 the given class is used for Javadoc generation only, but needs to - * be referenced for Checkstyle. With this, the classes in question are - * genuinely used, but only at the source level; no runtime code is generated. - * - * @author Donal Fellows - */ -@Retention(SOURCE) -@Target({ TYPE, METHOD, CONSTRUCTOR, FIELD }) -public @interface UsedInJavadocOnly { - /** - * Class or classes just used by the annotated thing in Javadoc generation. - * Put in with this so Checkstyle doesn't think the class is unused. - * - * @return classes - */ - Class[] value(); -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +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 the given class is used for Javadoc generation only, but needs to + * be referenced for Checkstyle. With this, the classes in question are + * genuinely used, but only at the source level; no runtime code is generated. + * + * @author Donal Fellows + */ +@Retention(SOURCE) +@Target({ TYPE, METHOD, CONSTRUCTOR, FIELD }) +public @interface UsedInJavadocOnly { + /** + * Class or classes just used by the annotated thing in Javadoc generation. + * Put in with this so Checkstyle doesn't think the class is unused. + * + * @return classes + */ + Class[] value(); +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java index 5b5c4e1991..a219507a77 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java @@ -1,126 +1,126 @@ -/* - * 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 - * - * http://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.utils.validation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.Payload; - -/** - * Validates that a number looks like a TCP port. Always accepts {@code null}. - * - * @author Donal Fellows - * @see UDPPort - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = TCPPort.Validator.class) -public @interface TCPPort { - /** The minimum ordinary TCP port number. */ - int MIN_TCP_PORT = 1024; - - /** The maximum TCP port number. */ - int MAX_TCP_PORT = 65535; - - /** - * Whether to allow the "any" port. Note that this is not the same as - * allowing any other port; it's more that it isn't bound to a specific - * port. - * - * @return Whether 0 is allowed. - */ - boolean any() default false; - - /** - * Whether to allow system ports. - * - * @return Whether 1-1023 is allowed. - */ - boolean system() default false; - - /** - * Whether to allow ephemeral ports. - * - * @return Whether 32768-65535 is allowed - */ - boolean ephemeral() default true; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad TCP port"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; - - /** - * Validator for {@link TCPPort} constraints. Not intended for direct use. - */ - class Validator implements ConstraintValidator { - private static final int MAX_STD_PORT = 32767; - - private boolean acceptZero; - - private int min; - - private int max; - - @Override - public void initialize(TCPPort annotation) { - acceptZero = annotation.any(); - min = annotation.system() ? 1 : TCPPort.MIN_TCP_PORT; - max = annotation.ephemeral() ? TCPPort.MAX_TCP_PORT : MAX_STD_PORT; - } - - @Override - public boolean isValid(Integer value, - ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - if (value == 0) { - return acceptZero; - } - return (value >= min) && (value <= max); - } - } -} +/* + * 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 + * + * http://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.utils.validation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.Payload; + +/** + * Validates that a number looks like a TCP port. Always accepts {@code null}. + * + * @author Donal Fellows + * @see UDPPort + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = TCPPort.Validator.class) +public @interface TCPPort { + /** The minimum ordinary TCP port number. */ + int MIN_TCP_PORT = 1024; + + /** The maximum TCP port number. */ + int MAX_TCP_PORT = 65535; + + /** + * Whether to allow the "any" port. Note that this is not the same as + * allowing any other port; it's more that it isn't bound to a specific + * port. + * + * @return Whether 0 is allowed. + */ + boolean any() default false; + + /** + * Whether to allow system ports. + * + * @return Whether 1-1023 is allowed. + */ + boolean system() default false; + + /** + * Whether to allow ephemeral ports. + * + * @return Whether 32768-65535 is allowed + */ + boolean ephemeral() default true; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad TCP port"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; + + /** + * Validator for {@link TCPPort} constraints. Not intended for direct use. + */ + class Validator implements ConstraintValidator { + private static final int MAX_STD_PORT = 32767; + + private boolean acceptZero; + + private int min; + + private int max; + + @Override + public void initialize(TCPPort annotation) { + acceptZero = annotation.any(); + min = annotation.system() ? 1 : TCPPort.MIN_TCP_PORT; + max = annotation.ephemeral() ? TCPPort.MAX_TCP_PORT : MAX_STD_PORT; + } + + @Override + public boolean isValid(Integer value, + ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + if (value == 0) { + return acceptZero; + } + return (value >= min) && (value <= max); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java index 4b100aee13..7856b2ba85 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java @@ -1,125 +1,125 @@ -/* - * 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 - * - * http://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.utils.validation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.validation.Constraint; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.Payload; - -/** - * Validates that a number looks like a UDP port. Always accepts {@code null}. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = UDPPort.Validator.class) -public @interface UDPPort { - /** The minimum ordinary UDP port number. */ - int MIN_UDP_PORT = 1024; - - /** The maximum UDP port number. */ - int MAX_UDP_PORT = 65535; - - /** - * Whether to allow the "any" port. Note that this is not the same as - * allowing any other port; it's more that it isn't bound to a specific - * port. - * - * @return Whether 0 is allowed. - */ - boolean any() default false; - - /** - * Whether to allow system ports. - * - * @return Whether 1-1023 is allowed. - */ - boolean system() default false; - - /** - * Whether to allow ephemeral ports. - * - * @return Whether 32768-65535 is allowed - */ - boolean ephemeral() default true; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad UDP port"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; - - /** - * Validator for {@link UDPPort} constraints. Not intended for direct use. - */ - class Validator implements ConstraintValidator { - private static final int MAX_STD_PORT = 32767; - - private boolean acceptZero; - - private int min; - - private int max; - - @Override - public void initialize(UDPPort annotation) { - acceptZero = annotation.any(); - min = annotation.system() ? 1 : UDPPort.MIN_UDP_PORT; - max = annotation.ephemeral() ? UDPPort.MAX_UDP_PORT : MAX_STD_PORT; - } - - @Override - public boolean isValid(Integer value, - ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - if (value == 0) { - return acceptZero; - } - return (value >= min) && (value <= max); - } - } -} +/* + * 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 + * + * http://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.utils.validation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.Payload; + +/** + * Validates that a number looks like a UDP port. Always accepts {@code null}. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = UDPPort.Validator.class) +public @interface UDPPort { + /** The minimum ordinary UDP port number. */ + int MIN_UDP_PORT = 1024; + + /** The maximum UDP port number. */ + int MAX_UDP_PORT = 65535; + + /** + * Whether to allow the "any" port. Note that this is not the same as + * allowing any other port; it's more that it isn't bound to a specific + * port. + * + * @return Whether 0 is allowed. + */ + boolean any() default false; + + /** + * Whether to allow system ports. + * + * @return Whether 1-1023 is allowed. + */ + boolean system() default false; + + /** + * Whether to allow ephemeral ports. + * + * @return Whether 32768-65535 is allowed + */ + boolean ephemeral() default true; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad UDP port"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; + + /** + * Validator for {@link UDPPort} constraints. Not intended for direct use. + */ + class Validator implements ConstraintValidator { + private static final int MAX_STD_PORT = 32767; + + private boolean acceptZero; + + private int min; + + private int max; + + @Override + public void initialize(UDPPort annotation) { + acceptZero = annotation.any(); + min = annotation.system() ? 1 : UDPPort.MIN_UDP_PORT; + max = annotation.ephemeral() ? UDPPort.MAX_UDP_PORT : MAX_STD_PORT; + } + + @Override + public boolean isValid(Integer value, + ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + if (value == 0) { + return acceptZero; + } + return (value >= min) && (value <= max); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java index 607a29d49c..461b0c7059 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java @@ -1,19 +1,19 @@ -/* - * 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 - * - * http://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. - */ -/** - * Utilities for validation of things. - */ -package uk.ac.manchester.spinnaker.utils.validation; +/* + * 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 + * + * http://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. + */ +/** + * Utilities for validation of things. + */ +package uk.ac.manchester.spinnaker.utils.validation; diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java index e7310c1276..312af036ff 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java @@ -1,129 +1,129 @@ -/* - * 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 - * - * http://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.utils; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -/** - * - * @author Christian - */ -public class TestOneShotEvent { - private static void sleep(int ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - System.err.println("unexpected wake from sleep"); - } - } - - public TestOneShotEvent() { - } - - private Runnable hanger = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.await(); - event.fire(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private Runnable inOrder = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.fire(); - event.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private Runnable firer = new Runnable() { - @Override - public void run() { - var event = new OneShotEvent(); - event.fire(); - } - }; - - private Runnable multiple = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.fire(); - event.fire(); - event.await(); - event.await(); - event.fire(); - event.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private OneShotEvent event1 = new OneShotEvent(); - - private Runnable waiter = new Runnable() { - @Override - public void run() { - try { - event1.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - @Test - public void testMultiple() { - var thanger = new Thread(hanger); - thanger.start(); - var tinOrder = new Thread(inOrder); - tinOrder.start(); - var tfirer = new Thread(firer); - tfirer.start(); - var tmultiple = new Thread(multiple); - tmultiple.start(); - var twaiter = new Thread(waiter); - twaiter.start(); - - sleep(500); - - assertTrue(thanger.isAlive()); - thanger.interrupt(); - assertTrue(!tinOrder.isAlive()); - assertTrue(!tfirer.isAlive()); - assertTrue(!tmultiple.isAlive()); - assertTrue(twaiter.isAlive()); - event1.fire(); - - sleep(50); - - assertTrue(!twaiter.isAlive()); - } - -} +/* + * 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 + * + * http://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.utils; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * + * @author Christian + */ +public class TestOneShotEvent { + private static void sleep(int ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.err.println("unexpected wake from sleep"); + } + } + + public TestOneShotEvent() { + } + + private Runnable hanger = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.await(); + event.fire(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private Runnable inOrder = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.fire(); + event.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private Runnable firer = new Runnable() { + @Override + public void run() { + var event = new OneShotEvent(); + event.fire(); + } + }; + + private Runnable multiple = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.fire(); + event.fire(); + event.await(); + event.await(); + event.fire(); + event.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private OneShotEvent event1 = new OneShotEvent(); + + private Runnable waiter = new Runnable() { + @Override + public void run() { + try { + event1.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + @Test + public void testMultiple() { + var thanger = new Thread(hanger); + thanger.start(); + var tinOrder = new Thread(inOrder); + tinOrder.start(); + var tfirer = new Thread(firer); + tfirer.start(); + var tmultiple = new Thread(multiple); + tmultiple.start(); + var twaiter = new Thread(waiter); + twaiter.start(); + + sleep(500); + + assertTrue(thanger.isAlive()); + thanger.interrupt(); + assertTrue(!tinOrder.isAlive()); + assertTrue(!tfirer.isAlive()); + assertTrue(!tmultiple.isAlive()); + assertTrue(twaiter.isAlive()); + event1.fire(); + + sleep(50); + + assertTrue(!twaiter.isAlive()); + } + +} diff --git a/src/support/javadoc/com.fasterxml.jackson.core/package-list b/src/support/javadoc/com.fasterxml.jackson.core/package-list index bb8a79efb8..87b90659df 100644 --- a/src/support/javadoc/com.fasterxml.jackson.core/package-list +++ b/src/support/javadoc/com.fasterxml.jackson.core/package-list @@ -1,14 +1,14 @@ -com.fasterxml.jackson.core -com.fasterxml.jackson.core.async -com.fasterxml.jackson.core.base -com.fasterxml.jackson.core.exc -com.fasterxml.jackson.core.filter -com.fasterxml.jackson.core.format -com.fasterxml.jackson.core.io -com.fasterxml.jackson.core.io.doubleparser -com.fasterxml.jackson.core.io.schubfach -com.fasterxml.jackson.core.json -com.fasterxml.jackson.core.json.async -com.fasterxml.jackson.core.sym -com.fasterxml.jackson.core.type -com.fasterxml.jackson.core.util +com.fasterxml.jackson.core +com.fasterxml.jackson.core.async +com.fasterxml.jackson.core.base +com.fasterxml.jackson.core.exc +com.fasterxml.jackson.core.filter +com.fasterxml.jackson.core.format +com.fasterxml.jackson.core.io +com.fasterxml.jackson.core.io.doubleparser +com.fasterxml.jackson.core.io.schubfach +com.fasterxml.jackson.core.json +com.fasterxml.jackson.core.json.async +com.fasterxml.jackson.core.sym +com.fasterxml.jackson.core.type +com.fasterxml.jackson.core.util diff --git a/src/support/javadoc/com.fasterxml.jackson.databind/package-list b/src/support/javadoc/com.fasterxml.jackson.databind/package-list index 3dce032c20..504478f4c2 100644 --- a/src/support/javadoc/com.fasterxml.jackson.databind/package-list +++ b/src/support/javadoc/com.fasterxml.jackson.databind/package-list @@ -1,23 +1,23 @@ -com.fasterxml.jackson.databind -com.fasterxml.jackson.databind.annotation -com.fasterxml.jackson.databind.cfg -com.fasterxml.jackson.databind.deser -com.fasterxml.jackson.databind.deser.impl -com.fasterxml.jackson.databind.deser.std -com.fasterxml.jackson.databind.exc -com.fasterxml.jackson.databind.ext -com.fasterxml.jackson.databind.introspect -com.fasterxml.jackson.databind.jdk14 -com.fasterxml.jackson.databind.json -com.fasterxml.jackson.databind.jsonFormatVisitors -com.fasterxml.jackson.databind.jsonschema -com.fasterxml.jackson.databind.jsontype -com.fasterxml.jackson.databind.jsontype.impl -com.fasterxml.jackson.databind.module -com.fasterxml.jackson.databind.node -com.fasterxml.jackson.databind.ser -com.fasterxml.jackson.databind.ser.impl -com.fasterxml.jackson.databind.ser.std -com.fasterxml.jackson.databind.type -com.fasterxml.jackson.databind.util -com.fasterxml.jackson.databind.util.internal +com.fasterxml.jackson.databind +com.fasterxml.jackson.databind.annotation +com.fasterxml.jackson.databind.cfg +com.fasterxml.jackson.databind.deser +com.fasterxml.jackson.databind.deser.impl +com.fasterxml.jackson.databind.deser.std +com.fasterxml.jackson.databind.exc +com.fasterxml.jackson.databind.ext +com.fasterxml.jackson.databind.introspect +com.fasterxml.jackson.databind.jdk14 +com.fasterxml.jackson.databind.json +com.fasterxml.jackson.databind.jsonFormatVisitors +com.fasterxml.jackson.databind.jsonschema +com.fasterxml.jackson.databind.jsontype +com.fasterxml.jackson.databind.jsontype.impl +com.fasterxml.jackson.databind.module +com.fasterxml.jackson.databind.node +com.fasterxml.jackson.databind.ser +com.fasterxml.jackson.databind.ser.impl +com.fasterxml.jackson.databind.ser.std +com.fasterxml.jackson.databind.type +com.fasterxml.jackson.databind.util +com.fasterxml.jackson.databind.util.internal diff --git a/src/support/javadoc/javax.validation/package-list b/src/support/javadoc/javax.validation/package-list index d37f56a720..35d7d788c6 100644 --- a/src/support/javadoc/javax.validation/package-list +++ b/src/support/javadoc/javax.validation/package-list @@ -1,9 +1,9 @@ -javax.validation -javax.validation.bootstrap -javax.validation.constraints -javax.validation.constraintvalidation -javax.validation.executable -javax.validation.groups -javax.validation.metadata -javax.validation.spi -javax.validation.valueextraction +javax.validation +javax.validation.bootstrap +javax.validation.constraints +javax.validation.constraintvalidation +javax.validation.executable +javax.validation.groups +javax.validation.metadata +javax.validation.spi +javax.validation.valueextraction diff --git a/src/support/javadoc/javax.ws.rs/package-list b/src/support/javadoc/javax.ws.rs/package-list index 810aa277d1..0f5b575cd3 100644 --- a/src/support/javadoc/javax.ws.rs/package-list +++ b/src/support/javadoc/javax.ws.rs/package-list @@ -1,6 +1,6 @@ -javax.ws.rs -javax.ws.rs.client -javax.ws.rs.container -javax.ws.rs.core -javax.ws.rs.ext -javax.ws.rs.sse +javax.ws.rs +javax.ws.rs.client +javax.ws.rs.container +javax.ws.rs.core +javax.ws.rs.ext +javax.ws.rs.sse diff --git a/src/support/javadoc/org.keycloak.client/package-list b/src/support/javadoc/org.keycloak.client/package-list index 417deb7052..1e9ccad13c 100644 --- a/src/support/javadoc/org.keycloak.client/package-list +++ b/src/support/javadoc/org.keycloak.client/package-list @@ -1 +1 @@ -org.keycloak.client.registration +org.keycloak.client.registration diff --git a/src/support/javadoc/org.keycloak.core/package-list b/src/support/javadoc/org.keycloak.core/package-list index 798d164b5f..52a90f9943 100644 --- a/src/support/javadoc/org.keycloak.core/package-list +++ b/src/support/javadoc/org.keycloak.core/package-list @@ -1,3 +1,3 @@ -org.keycloak -org.keycloak.representations -org.keycloak.representations.idm +org.keycloak +org.keycloak.representations +org.keycloak.representations.idm From 811be179bf5f0a2b94c3ef07420e954244512ebc Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 14 Feb 2023 09:01:50 +0000 Subject: [PATCH 057/194] More strongly label what is text for git --- .gitattributes | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 1564a7b813..68b9f5322c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +* text *.sql linguist-language=SQL linguist-detectable *.cff linguist-language=YAML *.json linguist-detectable @@ -5,8 +6,12 @@ *.yml linguist-detectable *.cfg linguist-language=INI linguist-detectable *.properties linguist-language=Java-Properties linguist-detectable -*.bin -linguist-generated -*.boot -linguist-generated -*.aplx -linguist-generated +*.bin binary -linguist-generated +*.boot binary -linguist-generated +*.aplx binary -linguist-generated *.fig linguist-documentation SpiNNaker-py2json/src/main/python/enum.py linguist-vendored +*.bit binary -linguist-generated +*.png binary +*.jpg binary +*/package-list linguist-generated From 8acb2bf6e273df0faef51df295405727345616de Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 14 Feb 2023 12:56:59 +0000 Subject: [PATCH 058/194] eolfix --- .mvn/jvm.config | 20 +- .../spinnaker/alloc/ForTestingOnly.java | 152 +- .../manchester/spinnaker/alloc/IOUtils.java | 150 +- .../alloc/admin/AdminControllerSupport.java | 890 +++++------ .../alloc/admin/ReportMailSender.java | 186 +-- .../alloc/bmp/BlacklistOperation.java | 62 +- .../spinnaker/alloc/bmp/BlacklistStore.java | 402 ++--- .../alloc/bmp/PhysicalSerialMapping.java | 234 +-- .../spinnaker/alloc/compat/SaneParameter.java | 152 +- .../spinnaker/alloc/compat/TaskException.java | 64 +- .../spinnaker/alloc/db/DatabaseAPI.java | 1298 ++++++++--------- .../spinnaker/alloc/db/SQLQueries.java | 4 +- .../spinnaker/alloc/model/JavaBean.java | 80 +- .../spinnaker/alloc/model/Utils.java | 110 +- .../alloc/security/OpenIDUserAware.java | 200 +-- ...itional-spring-configuration-metadata.json | 2 +- .../spinnaker/alloc/SupportQueries.java | 450 +++--- .../spinnaker/alloc/TestSupport.java | 1082 +++++++------- .../spinnaker/alloc/bmp/MockTransceiver.java | 582 ++++---- .../spinnaker/alloc/db/MemDBTestBase.java | 130 +- .../test/resources/three-board-example.json | 2 +- .../spinnaker/alloc/client/ClientUtils.java | 172 +-- .../alloc/client/ProxiedBootConnection.java | 208 +-- .../ProxiedEIEIOListenerConnection.java | 194 +-- .../alloc/client/ProxiedSCPConnection.java | 230 +-- .../alloc/client/ProxiedTransceiver.java | 182 +-- .../spinnaker/alloc/client/ProxyProtocol.java | 106 +- .../alloc/client/ProxyProtocolClient.java | 232 +-- .../spinnaker/alloc/client/Session.java | 400 ++--- .../manchester/spinnaker/messages/Utils.java | 90 +- .../spinnaker/messages/model/Addresses.java | 60 +- .../spinnaker/messages/model/Blacklist.java | 1106 +++++++------- .../messages/model/SerialVector.java | 156 +- .../messages/model/TagDescription.java | 236 +-- .../spinnaker/messages/model/TagInfo.java | 70 +- .../model/UnroutableMessageException.java | 90 +- .../messages/scp/ConnectionAwareMessage.java | 82 +- .../spinnaker/messages/scp/EmptyResponse.java | 84 +- .../spinnaker/messages/scp/FECRequest.java | 172 +-- .../messages/scp/FloodFillConstants.java | 82 +- .../messages/scp/PayloadedResponse.java | 122 +- .../messages/scp/ReinjectorRequest.java | 188 +-- .../messages/scp/RouterTableRequest.java | 152 +- .../spinnaker/spalloc/messages/BoardLink.java | 98 +- .../transceiver/CommonMemoryLocations.java | 218 +-- .../spinnaker/messages/model/TestVersion.java | 116 +- .../spinnaker/spalloc/TestClient.java | 2 +- .../manchester/spinnaker/spalloc/TestJob.java | 2 +- .../messages/TestBoardCoordinates.java | 94 +- .../TestBoardPhysicalCoordinates.java | 94 +- .../spalloc/messages/TestJobDescription.java | 192 +-- .../spalloc/messages/TestJobMachineInfo.java | 170 +-- .../spalloc/messages/TestMachine.java | 240 +-- .../spinnaker/spalloc/messages/TestState.java | 142 +- .../spalloc/messages/TestWhereIs.java | 266 ++-- .../src/test/resources/spinn2.json | 2 +- .../src/test/resources/spinn4.json | 2 +- .../spinnaker/alloc/bmp/example.blacklist | 36 +- .../spinnaker/front_end/DebuggingUtils.java | 192 +-- .../dse/ExecuteDataSpecification.java | 254 ++-- .../src/test/resources/gather.json | 2 +- .../src/test/resources/machine.json | 32 +- .../src/test/resources/simple.json | 2 +- .../spinnaker/front_end/iobuf/empty.dict | 32 +- .../spinnaker/machine/MemoryLocation.java | 302 ++-- .../spinnaker/machine/ValidMachineHeight.java | 138 +- .../spinnaker/machine/ValidMachineWidth.java | 138 +- .../manchester/spinnaker/machine/ValidP.java | 136 +- .../manchester/spinnaker/machine/ValidX.java | 136 +- .../manchester/spinnaker/machine/ValidY.java | 136 +- .../spinnaker/machine/board/BMPCoords.java | 302 ++-- .../machine/board/DeserializerHelper.java | 422 +++--- .../spinnaker/machine/board/Limits.java | 94 +- .../machine/board/PhysicalCoords.java | 340 ++--- .../spinnaker/machine/board/TriadCoords.java | 386 ++--- .../machine/board/ValidBoardNumber.java | 138 +- .../machine/board/ValidCabinetNumber.java | 138 +- .../machine/board/ValidFrameNumber.java | 138 +- .../machine/board/ValidTriadDepth.java | 140 +- .../machine/board/ValidTriadHeight.java | 136 +- .../machine/board/ValidTriadWidth.java | 136 +- .../spinnaker/machine/board/ValidTriadX.java | 136 +- .../spinnaker/machine/board/ValidTriadY.java | 136 +- .../spinnaker/machine/board/ValidTriadZ.java | 136 +- .../spinnaker/machine/board/package-info.java | 42 +- .../spinnaker/machine/tags/TagID.java | 206 +-- .../src/test/resources/h40w16.json | 2 +- .../src/test/resources/spinn2.json | 2 +- .../src/test/resources/spinn4.json | 2 +- .../src/test/resources/spinn4_fiddle.json | 2 +- .../src/test/resources/test24_12.json | 2 +- SpiNNaker-pacman/src/test/java/.gitignore | 1 + .../spinnaker/py2json/Configuration.java | 164 +-- .../ac/manchester/spinnaker/py2json/Link.java | 86 +- .../manchester/spinnaker/py2json/Machine.java | 354 ++--- .../py2json/WithCurrentDirectory.java | 116 +- .../spinnaker/py2json/three_board.py | 82 +- .../spinnaker/storage/sqlite/Ordinals.java | 74 +- .../storage/sqlite/ResourceLoader.java | 122 +- .../spinnaker/utils/ByteBufferUtils.java | 256 ++-- .../spinnaker/utils/CollectionUtils.java | 586 ++++---- .../ac/manchester/spinnaker/utils/Daemon.java | 166 +-- .../spinnaker/utils/UsedInJavadocOnly.java | 88 +- .../spinnaker/utils/validation/TCPPort.java | 252 ++-- .../spinnaker/utils/validation/UDPPort.java | 250 ++-- .../utils/validation/package-info.java | 38 +- .../spinnaker/utils/TestOneShotEvent.java | 258 ++-- .../com.fasterxml.jackson.core/package-list | 28 +- .../package-list | 46 +- .../javadoc/javax.validation/package-list | 18 +- src/support/javadoc/javax.ws.rs/package-list | 12 +- .../javadoc/org.keycloak.client/package-list | 2 +- .../javadoc/org.keycloak.core/package-list | 6 +- 113 files changed, 9941 insertions(+), 9940 deletions(-) diff --git a/.mvn/jvm.config b/.mvn/jvm.config index 3ed5dea48c..32599cefea 100644 --- a/.mvn/jvm.config +++ b/.mvn/jvm.config @@ -1,10 +1,10 @@ ---add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED ---add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED ---add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ---add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java index cdd19fecd9..302eed6fd3 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ForTestingOnly.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; - -import java.lang.StackWalker.StackFrame; -import java.lang.annotation.Annotation; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.Arrays; - -/** - * Marks a type or method that only exists for testing purposes. Do not use for - * any other reason! Methods tagged with this should also be tagged - * {@link Deprecated @Deprecated}; classes/interfaces tagged with this need not. - * - * @author Donal Fellows - */ -@Documented -@Retention(CLASS) -@Target({ TYPE, METHOD }) -public @interface ForTestingOnly { - /** Utilities for checking the promises relating to the annotation. */ - abstract class Utils { - /** - * The name of the class used to annotate tests that can access - * bean test APIs. - */ - private static final String SPRING_BOOT_TEST = - "org.springframework.boot.test.context.SpringBootTest"; - - private Utils() { - } - - /** - * A simple test for whether there are classes annotated with - * {@code @SpringBootTest} on the stack at the point it is called. - * Moderately expensive, but it only guards stuff that should be used on - * test paths, so that isn't important. - * - * @throws Error - * if not called from the right place; it's a serious - * security failure and wrong programming. - */ - // No link to doc; built in code that doesn't see test classes - public static void checkForTestClassOnStack() { - if (!StackWalker.getInstance(RETAIN_CLASS_REFERENCE) - .walk(s -> s.map(StackFrame::getDeclaringClass) // - .map(Class::getAnnotations) // - .flatMap(Arrays::stream) // - .map(Annotation::annotationType) // - .map(Class::getName) // - .anyMatch(SPRING_BOOT_TEST::equals))) { - throw new Error("test-only code called from non-test context"); - } - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.StackWalker.StackFrame; +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.Arrays; + +/** + * Marks a type or method that only exists for testing purposes. Do not use for + * any other reason! Methods tagged with this should also be tagged + * {@link Deprecated @Deprecated}; classes/interfaces tagged with this need not. + * + * @author Donal Fellows + */ +@Documented +@Retention(CLASS) +@Target({ TYPE, METHOD }) +public @interface ForTestingOnly { + /** Utilities for checking the promises relating to the annotation. */ + abstract class Utils { + /** + * The name of the class used to annotate tests that can access + * bean test APIs. + */ + private static final String SPRING_BOOT_TEST = + "org.springframework.boot.test.context.SpringBootTest"; + + private Utils() { + } + + /** + * A simple test for whether there are classes annotated with + * {@code @SpringBootTest} on the stack at the point it is called. + * Moderately expensive, but it only guards stuff that should be used on + * test paths, so that isn't important. + * + * @throws Error + * if not called from the right place; it's a serious + * security failure and wrong programming. + */ + // No link to doc; built in code that doesn't see test classes + public static void checkForTestClassOnStack() { + if (!StackWalker.getInstance(RETAIN_CLASS_REFERENCE) + .walk(s -> s.map(StackFrame::getDeclaringClass) // + .map(Class::getAnnotations) // + .flatMap(Arrays::stream) // + .map(Annotation::annotationType) // + .map(Class::getName) // + .anyMatch(SPRING_BOOT_TEST::equals))) { + throw new Error("test-only code called from non-test context"); + } + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java index 94a0c0df2c..411b63ee57 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/IOUtils.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * Utility wrappers for I/O. - * - * @author Donal Fellows - */ -public abstract class IOUtils { - private IOUtils() { - } - - /** - * Convert a serializable object into its serialized form. - * - * @param obj - * The object to serialize. - * @return The serialized form. - * @throws IOException - * If the object isn't serializable. - */ - public static byte[] serialize(Object obj) throws IOException { - var baos = new ByteArrayOutputStream(); - try (var oos = new ObjectOutputStream(baos)) { - oos.writeObject(obj); - } - return baos.toByteArray(); - } - - /** - * Convert a serialized object into its normal form. Only call on - * data that is trusted! - * - * @param - * The type of the response. - * @param bytes - * The serialized data. - * @param cls - * The class that the object is expected to conform to. - * @return The deserialized object. - * @throws IOException - * If the object isn't deserializable. - * @throws ClassNotFoundException - * If the data doesn't represent a known class. - * @throws ClassCastException - * If the data is not an object of the expected class. - */ - public static T deserialize(byte[] bytes, Class cls) - throws ClassNotFoundException, IOException { - var bais = new ByteArrayInputStream(bytes); - try (var ois = new ObjectInputStream(bais)) { - return cls.cast(ois.readObject()); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Utility wrappers for I/O. + * + * @author Donal Fellows + */ +public abstract class IOUtils { + private IOUtils() { + } + + /** + * Convert a serializable object into its serialized form. + * + * @param obj + * The object to serialize. + * @return The serialized form. + * @throws IOException + * If the object isn't serializable. + */ + public static byte[] serialize(Object obj) throws IOException { + var baos = new ByteArrayOutputStream(); + try (var oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } + return baos.toByteArray(); + } + + /** + * Convert a serialized object into its normal form. Only call on + * data that is trusted! + * + * @param + * The type of the response. + * @param bytes + * The serialized data. + * @param cls + * The class that the object is expected to conform to. + * @return The deserialized object. + * @throws IOException + * If the object isn't deserializable. + * @throws ClassNotFoundException + * If the data doesn't represent a known class. + * @throws ClassCastException + * If the data is not an object of the expected class. + */ + public static T deserialize(byte[] bytes, Class cls) + throws ClassNotFoundException, IOException { + var bais = new ByteArrayInputStream(bytes); + try (var ois = new ObjectInputStream(bais)) { + return cls.cast(ois.readObject()); + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java index ccd1508016..fa02497616 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerSupport.java @@ -1,445 +1,445 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.admin; - -import static java.util.Collections.unmodifiableMap; - -import java.net.URI; -import java.util.List; -import java.util.Map; - -import org.springframework.ui.ModelMap; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; - -import uk.ac.manchester.spinnaker.alloc.admin.AdminController.BlacklistData; -import uk.ac.manchester.spinnaker.alloc.admin.MachineDefinitionLoader.Machine; -import uk.ac.manchester.spinnaker.alloc.model.BoardIssueReport; -import uk.ac.manchester.spinnaker.alloc.model.BoardRecord; -import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; -import uk.ac.manchester.spinnaker.alloc.model.MachineTagging; -import uk.ac.manchester.spinnaker.alloc.model.UserRecord; -import uk.ac.manchester.spinnaker.alloc.model.GroupRecord.GroupType; -import uk.ac.manchester.spinnaker.alloc.security.TrustLevel; -import uk.ac.manchester.spinnaker.alloc.web.ControllerUtils.ViewFactory; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * Support code for {@link AdminController}. - */ -@UsedInJavadocOnly({ GroupType.class, BoardIssueReport.class }) -interface AdminControllerSupport { - // These are paths below src/main/webapp/WEB-INF/views - /** View: {@code admin/index.jsp}. */ - ViewFactory MAIN_VIEW = new ViewFactory("admin/index"); - - /** View: {@code admin/listusers.jsp}. */ - ViewFactory USER_LIST_VIEW = new ViewFactory("admin/listusers"); - - /** View: {@code admin/userdetails.jsp}. */ - ViewFactory USER_DETAILS_VIEW = new ViewFactory("admin/userdetails"); - - /** View: {@code admin/createuser.jsp}. */ - ViewFactory CREATE_USER_VIEW = new ViewFactory("admin/createuser"); - - /** View: {@code admin/listgroups.jsp}. */ - ViewFactory GROUP_LIST_VIEW = new ViewFactory("admin/listgroups"); - - /** View: {@code admin/groupdetails.jsp}. */ - ViewFactory GROUP_DETAILS_VIEW = new ViewFactory("admin/groupdetails"); - - /** View: {@code admin/creategroup.jsp}. */ - ViewFactory CREATE_GROUP_VIEW = new ViewFactory("admin/creategroup"); - - /** View: {@code admin/board.jsp}. */ - ViewFactory BOARD_VIEW = new ViewFactory("admin/board"); - - /** View: {@code admin/machine.jsp}. */ - ViewFactory MACHINE_VIEW = new ViewFactory("admin/machine"); - - /** User list in {@link #USER_LIST_VIEW}. All users. */ - String USER_LIST_OBJ = "userlist"; - - /** User list in {@link #USER_LIST_VIEW}. Local users only. */ - String LOCAL_USER_LIST_OBJ = "localusers"; - - /** User list in {@link #USER_LIST_VIEW}. OpenID users only. */ - String OPENID_USER_LIST_OBJ = "openidusers"; - - /** User details in {@link #USER_DETAILS_VIEW}. */ - String USER_OBJ = "user"; - - /** - * Group list (type: {@link GroupType#INTERNAL}) in - * {@link #GROUP_LIST_VIEW}. - */ - String LOCAL_GROUP_LIST_OBJ = "localgroups"; - - /** - * Group list (type: {@link GroupType#ORGANISATION}) in - * {@link #GROUP_LIST_VIEW}. - */ - String ORG_GROUP_LIST_OBJ = "orggroups"; - - /** - * Group list (type: {@link GroupType#COLLABRATORY}) in - * {@link #GROUP_LIST_VIEW}. - */ - String COLLAB_GROUP_LIST_OBJ = "collabgroups"; - - /** - * Group details in {@link #GROUP_DETAILS_VIEW}. Group creation info in - * {@link #CREATE_GROUP_VIEW}. - */ - String GROUP_OBJ = "group"; - - /** State in {@link #BOARD_VIEW}. {@link BoardRecord}. */ - String BOARD_OBJ = "board"; - - /** - * Blacklist data in {@link #BOARD_VIEW}. {@link BlacklistData}. - */ - String BLACKLIST_DATA_OBJ = "bldata"; - - /** - * Mapping from machine names to whether they're in service, in - * {@link #MACHINE_VIEW}. - * {@link Map}{@code <}{@link String}{@code ,}{@link Boolean}{@code >} - */ - String MACHINE_LIST_OBJ = "machineNames"; - - /** - * Machines that have been defined, in {@link #MACHINE_VIEW}. - * - * @see Machine - */ - String DEFINED_MACHINES_OBJ = "definedMachines"; - - /** - * Result of {@link MachineStateControl#getMachineTagging()}, in - * {@link #MACHINE_VIEW}. - * - * @see MachineTagging - */ - String MACHINE_TAGGING_OBJ = "machineTagging"; - - /** - * Number of {@code default} tags in {@link #MACHINE_TAGGING_OBJ}, in - * {@link #MACHINE_VIEW}. - */ - String DEFAULT_TAGGING_COUNT = "defaultCount"; - - /** - * Result of {@link MachineStateControl#getMachineReports()}, in - * {@link #MACHINE_VIEW}. - * - * @see BoardIssueReport - */ - String MACHINE_REPORTS_OBJ = "machineReports"; - - /** The base URI for the current request. In all views. */ - String BASE_URI = "baseuri"; - - /** The members of {@link TrustLevel}. In all views. */ - String TRUST_LEVELS = "trustLevels"; - - /** - * How to call {@link AdminController#listUsers() listUsers()}. In all - * views. - */ - String USERS_URI = "usersUri"; - - /** - * How to call {@link AdminController#getUserCreationForm() - * getUserCreationForm()}. In all views. - */ - String CREATE_USER_URI = "createUserUri"; - - /** - * How to call {@link AdminController#listGroups() listGroups()}. In all - * views. - */ - String GROUPS_URI = "groupsUri"; - - /** - * How to call {@link AdminController#getGroupCreationForm() - * getGroupCreationForm()}. In all views. - */ - String CREATE_GROUP_URI = "createGroupUri"; - - /** How to call {@link AdminController#boards() boards()}. In all views. */ - String BOARDS_URI = "boardsUri"; - - /** - * How to call {@link AdminController#blacklistSave(BlacklistData,ModelMap) - * blacklistSave()}, - * {@link AdminController#blacklistPush(BlacklistData, ModelMap) - * blacklistPush()}, and - * {@link AdminController#blacklistFetch(BlacklistData,ModelMap) - * blacklistFetch()}. In {@link #BOARD_VIEW}. - */ - String BLACKLIST_URI = "blacklistControlUri"; - - /** - * How to call {@link AdminController#machineManagement() - * machineManagement()}. In all views. - */ - String MACHINE_URI = "machineUri"; - - // Type-safe manipulators for models - // These are static so they *can't* access state they shouldn't - - /** - * Add local user list to model. - * - * @param mav - * The model - * @param userList - * The user list to add. - */ - static void addLocalUserList(ModelAndView mav, Map userList) { - mav.addObject(LOCAL_USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add openid-based (remote) user list to model. - * - * @param mav - * The model - * @param userList - * The user list to add. - */ - static void addRemoteUserList(ModelAndView mav, Map userList) { - mav.addObject(OPENID_USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add general user list to model. - * - * @param mav - * The model - * @param userList - * The group list to add. - */ - static void addUserList(ModelAndView mav, Map userList) { - mav.addObject(USER_LIST_OBJ, unmodifiableMap(userList)); - } - - /** - * Add user record to model. - * - * @param mav - * The model - * @param user - * The user record to add. - */ - static void addUser(ModelAndView mav, UserRecord user) { - mav.addObject(USER_OBJ, user.sanitise()); - } - - /** - * Add user record to model. - * - * @param attrs - * The model - * @param user - * The user record to add. - */ - static void addUser(RedirectAttributes attrs, UserRecord user) { - attrs.addFlashAttribute(USER_OBJ, user); - } - - /** - * Add local group list to model. - * - * @param mav - * The model - * @param groupList - * The group list to add. - */ - static void addLocalGroupList(ModelAndView mav, - Map groupList) { - mav.addObject(LOCAL_GROUP_LIST_OBJ, unmodifiableMap(groupList)); - } - - /** - * Add organisation list to model. - * - * @param mav - * The model - * @param orgList - * The group list to add. - */ - static void addOrganisationList(ModelAndView mav, - Map orgList) { - mav.addObject(ORG_GROUP_LIST_OBJ, unmodifiableMap(orgList)); - } - - /** - * Add collabratory list to model. - * - * @param mav - * The model - * @param collabList - * The group list to add. - */ - static void addCollabratoryList(ModelAndView mav, - Map collabList) { - mav.addObject(COLLAB_GROUP_LIST_OBJ, unmodifiableMap(collabList)); - } - - /** - * Add group record to model. - * - * @param mav - * The model - * @param group - * The group record to add. - */ - static void addGroup(ModelAndView mav, GroupRecord group) { - mav.addObject(GROUP_OBJ, group); - } - - /** - * Add board record to model. - * - * @param mav - * The model - * @param board - * The board record to add. - */ - static void addBoard(ModelAndView mav, BoardRecord board) { - mav.addObject(BOARD_OBJ, board); - } - - /** - * Add board record to model. - * - * @param model - * The model - * @param board - * The board record to add. - */ - static void addBoard(ModelMap model, BoardRecord board) { - model.addAttribute(BOARD_OBJ, board); - } - - /** - * Add blacklist record to model. - * - * @param model - * The model - * @param bldata - * The blacklist record to add. - */ - static void addBlacklist(ModelMap model, BlacklistData bldata) { - model.addAttribute(BLACKLIST_DATA_OBJ, bldata); - } - - /** - * Add machine list to model. - * - * @param mav - * The model - * @param machineList - * The machine list to add. - */ - static void addMachineList(ModelAndView mav, - Map machineList) { - mav.addObject(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); - } - - /** - * Add machine list to model. - * - * @param model - * The model - * @param machineList - * The machine list to add. - */ - static void addMachineList(ModelMap model, - Map machineList) { - model.addAttribute(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); - } - - /** - * Add machine tagging to model. - * - * @param mav - * The model - * @param tagging - * The machine tagging to add. - */ - static void addMachineTagging(ModelAndView mav, - List tagging) { - mav.addObject(MACHINE_TAGGING_OBJ, tagging); - mav.addObject(DEFAULT_TAGGING_COUNT, tagging.stream() - .filter(MachineTagging::isTaggedAsDefault).count()); - } - - /** - * Add machine reports to model. - * - * @param mav - * The model - * @param reports - * The machine reports to add. - */ - static void addMachineReports(ModelAndView mav, - Map> reports) { - mav.addObject(MACHINE_REPORTS_OBJ, reports); - } - - /** - * Add link to model. - * - * @param mav - * The model - * @param handle - * The name of the link - * @param url - * The URL to add. - */ - static void addUrl(ModelAndView mav, String handle, URI url) { - mav.addObject(handle, url); - } - - /** - * Add link to model. - * - * @param model - * The model - * @param handle - * The name of the link - * @param url - * The URL to add. - */ - static void addUrl(ModelMap model, String handle, URI url) { - model.addAttribute(handle, url); - } - - /** - * Add notice message to model. - * - * @param attrs - * The model - * @param msg - * The notice message to add. - */ - static void addNotice(RedirectAttributes attrs, String msg) { - attrs.addFlashAttribute("notice", msg); - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.admin; + +import static java.util.Collections.unmodifiableMap; + +import java.net.URI; +import java.util.List; +import java.util.Map; + +import org.springframework.ui.ModelMap; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import uk.ac.manchester.spinnaker.alloc.admin.AdminController.BlacklistData; +import uk.ac.manchester.spinnaker.alloc.admin.MachineDefinitionLoader.Machine; +import uk.ac.manchester.spinnaker.alloc.model.BoardIssueReport; +import uk.ac.manchester.spinnaker.alloc.model.BoardRecord; +import uk.ac.manchester.spinnaker.alloc.model.GroupRecord; +import uk.ac.manchester.spinnaker.alloc.model.MachineTagging; +import uk.ac.manchester.spinnaker.alloc.model.UserRecord; +import uk.ac.manchester.spinnaker.alloc.model.GroupRecord.GroupType; +import uk.ac.manchester.spinnaker.alloc.security.TrustLevel; +import uk.ac.manchester.spinnaker.alloc.web.ControllerUtils.ViewFactory; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * Support code for {@link AdminController}. + */ +@UsedInJavadocOnly({ GroupType.class, BoardIssueReport.class }) +interface AdminControllerSupport { + // These are paths below src/main/webapp/WEB-INF/views + /** View: {@code admin/index.jsp}. */ + ViewFactory MAIN_VIEW = new ViewFactory("admin/index"); + + /** View: {@code admin/listusers.jsp}. */ + ViewFactory USER_LIST_VIEW = new ViewFactory("admin/listusers"); + + /** View: {@code admin/userdetails.jsp}. */ + ViewFactory USER_DETAILS_VIEW = new ViewFactory("admin/userdetails"); + + /** View: {@code admin/createuser.jsp}. */ + ViewFactory CREATE_USER_VIEW = new ViewFactory("admin/createuser"); + + /** View: {@code admin/listgroups.jsp}. */ + ViewFactory GROUP_LIST_VIEW = new ViewFactory("admin/listgroups"); + + /** View: {@code admin/groupdetails.jsp}. */ + ViewFactory GROUP_DETAILS_VIEW = new ViewFactory("admin/groupdetails"); + + /** View: {@code admin/creategroup.jsp}. */ + ViewFactory CREATE_GROUP_VIEW = new ViewFactory("admin/creategroup"); + + /** View: {@code admin/board.jsp}. */ + ViewFactory BOARD_VIEW = new ViewFactory("admin/board"); + + /** View: {@code admin/machine.jsp}. */ + ViewFactory MACHINE_VIEW = new ViewFactory("admin/machine"); + + /** User list in {@link #USER_LIST_VIEW}. All users. */ + String USER_LIST_OBJ = "userlist"; + + /** User list in {@link #USER_LIST_VIEW}. Local users only. */ + String LOCAL_USER_LIST_OBJ = "localusers"; + + /** User list in {@link #USER_LIST_VIEW}. OpenID users only. */ + String OPENID_USER_LIST_OBJ = "openidusers"; + + /** User details in {@link #USER_DETAILS_VIEW}. */ + String USER_OBJ = "user"; + + /** + * Group list (type: {@link GroupType#INTERNAL}) in + * {@link #GROUP_LIST_VIEW}. + */ + String LOCAL_GROUP_LIST_OBJ = "localgroups"; + + /** + * Group list (type: {@link GroupType#ORGANISATION}) in + * {@link #GROUP_LIST_VIEW}. + */ + String ORG_GROUP_LIST_OBJ = "orggroups"; + + /** + * Group list (type: {@link GroupType#COLLABRATORY}) in + * {@link #GROUP_LIST_VIEW}. + */ + String COLLAB_GROUP_LIST_OBJ = "collabgroups"; + + /** + * Group details in {@link #GROUP_DETAILS_VIEW}. Group creation info in + * {@link #CREATE_GROUP_VIEW}. + */ + String GROUP_OBJ = "group"; + + /** State in {@link #BOARD_VIEW}. {@link BoardRecord}. */ + String BOARD_OBJ = "board"; + + /** + * Blacklist data in {@link #BOARD_VIEW}. {@link BlacklistData}. + */ + String BLACKLIST_DATA_OBJ = "bldata"; + + /** + * Mapping from machine names to whether they're in service, in + * {@link #MACHINE_VIEW}. + * {@link Map}{@code <}{@link String}{@code ,}{@link Boolean}{@code >} + */ + String MACHINE_LIST_OBJ = "machineNames"; + + /** + * Machines that have been defined, in {@link #MACHINE_VIEW}. + * + * @see Machine + */ + String DEFINED_MACHINES_OBJ = "definedMachines"; + + /** + * Result of {@link MachineStateControl#getMachineTagging()}, in + * {@link #MACHINE_VIEW}. + * + * @see MachineTagging + */ + String MACHINE_TAGGING_OBJ = "machineTagging"; + + /** + * Number of {@code default} tags in {@link #MACHINE_TAGGING_OBJ}, in + * {@link #MACHINE_VIEW}. + */ + String DEFAULT_TAGGING_COUNT = "defaultCount"; + + /** + * Result of {@link MachineStateControl#getMachineReports()}, in + * {@link #MACHINE_VIEW}. + * + * @see BoardIssueReport + */ + String MACHINE_REPORTS_OBJ = "machineReports"; + + /** The base URI for the current request. In all views. */ + String BASE_URI = "baseuri"; + + /** The members of {@link TrustLevel}. In all views. */ + String TRUST_LEVELS = "trustLevels"; + + /** + * How to call {@link AdminController#listUsers() listUsers()}. In all + * views. + */ + String USERS_URI = "usersUri"; + + /** + * How to call {@link AdminController#getUserCreationForm() + * getUserCreationForm()}. In all views. + */ + String CREATE_USER_URI = "createUserUri"; + + /** + * How to call {@link AdminController#listGroups() listGroups()}. In all + * views. + */ + String GROUPS_URI = "groupsUri"; + + /** + * How to call {@link AdminController#getGroupCreationForm() + * getGroupCreationForm()}. In all views. + */ + String CREATE_GROUP_URI = "createGroupUri"; + + /** How to call {@link AdminController#boards() boards()}. In all views. */ + String BOARDS_URI = "boardsUri"; + + /** + * How to call {@link AdminController#blacklistSave(BlacklistData,ModelMap) + * blacklistSave()}, + * {@link AdminController#blacklistPush(BlacklistData, ModelMap) + * blacklistPush()}, and + * {@link AdminController#blacklistFetch(BlacklistData,ModelMap) + * blacklistFetch()}. In {@link #BOARD_VIEW}. + */ + String BLACKLIST_URI = "blacklistControlUri"; + + /** + * How to call {@link AdminController#machineManagement() + * machineManagement()}. In all views. + */ + String MACHINE_URI = "machineUri"; + + // Type-safe manipulators for models + // These are static so they *can't* access state they shouldn't + + /** + * Add local user list to model. + * + * @param mav + * The model + * @param userList + * The user list to add. + */ + static void addLocalUserList(ModelAndView mav, Map userList) { + mav.addObject(LOCAL_USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add openid-based (remote) user list to model. + * + * @param mav + * The model + * @param userList + * The user list to add. + */ + static void addRemoteUserList(ModelAndView mav, Map userList) { + mav.addObject(OPENID_USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add general user list to model. + * + * @param mav + * The model + * @param userList + * The group list to add. + */ + static void addUserList(ModelAndView mav, Map userList) { + mav.addObject(USER_LIST_OBJ, unmodifiableMap(userList)); + } + + /** + * Add user record to model. + * + * @param mav + * The model + * @param user + * The user record to add. + */ + static void addUser(ModelAndView mav, UserRecord user) { + mav.addObject(USER_OBJ, user.sanitise()); + } + + /** + * Add user record to model. + * + * @param attrs + * The model + * @param user + * The user record to add. + */ + static void addUser(RedirectAttributes attrs, UserRecord user) { + attrs.addFlashAttribute(USER_OBJ, user); + } + + /** + * Add local group list to model. + * + * @param mav + * The model + * @param groupList + * The group list to add. + */ + static void addLocalGroupList(ModelAndView mav, + Map groupList) { + mav.addObject(LOCAL_GROUP_LIST_OBJ, unmodifiableMap(groupList)); + } + + /** + * Add organisation list to model. + * + * @param mav + * The model + * @param orgList + * The group list to add. + */ + static void addOrganisationList(ModelAndView mav, + Map orgList) { + mav.addObject(ORG_GROUP_LIST_OBJ, unmodifiableMap(orgList)); + } + + /** + * Add collabratory list to model. + * + * @param mav + * The model + * @param collabList + * The group list to add. + */ + static void addCollabratoryList(ModelAndView mav, + Map collabList) { + mav.addObject(COLLAB_GROUP_LIST_OBJ, unmodifiableMap(collabList)); + } + + /** + * Add group record to model. + * + * @param mav + * The model + * @param group + * The group record to add. + */ + static void addGroup(ModelAndView mav, GroupRecord group) { + mav.addObject(GROUP_OBJ, group); + } + + /** + * Add board record to model. + * + * @param mav + * The model + * @param board + * The board record to add. + */ + static void addBoard(ModelAndView mav, BoardRecord board) { + mav.addObject(BOARD_OBJ, board); + } + + /** + * Add board record to model. + * + * @param model + * The model + * @param board + * The board record to add. + */ + static void addBoard(ModelMap model, BoardRecord board) { + model.addAttribute(BOARD_OBJ, board); + } + + /** + * Add blacklist record to model. + * + * @param model + * The model + * @param bldata + * The blacklist record to add. + */ + static void addBlacklist(ModelMap model, BlacklistData bldata) { + model.addAttribute(BLACKLIST_DATA_OBJ, bldata); + } + + /** + * Add machine list to model. + * + * @param mav + * The model + * @param machineList + * The machine list to add. + */ + static void addMachineList(ModelAndView mav, + Map machineList) { + mav.addObject(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); + } + + /** + * Add machine list to model. + * + * @param model + * The model + * @param machineList + * The machine list to add. + */ + static void addMachineList(ModelMap model, + Map machineList) { + model.addAttribute(MACHINE_LIST_OBJ, unmodifiableMap(machineList)); + } + + /** + * Add machine tagging to model. + * + * @param mav + * The model + * @param tagging + * The machine tagging to add. + */ + static void addMachineTagging(ModelAndView mav, + List tagging) { + mav.addObject(MACHINE_TAGGING_OBJ, tagging); + mav.addObject(DEFAULT_TAGGING_COUNT, tagging.stream() + .filter(MachineTagging::isTaggedAsDefault).count()); + } + + /** + * Add machine reports to model. + * + * @param mav + * The model + * @param reports + * The machine reports to add. + */ + static void addMachineReports(ModelAndView mav, + Map> reports) { + mav.addObject(MACHINE_REPORTS_OBJ, reports); + } + + /** + * Add link to model. + * + * @param mav + * The model + * @param handle + * The name of the link + * @param url + * The URL to add. + */ + static void addUrl(ModelAndView mav, String handle, URI url) { + mav.addObject(handle, url); + } + + /** + * Add link to model. + * + * @param model + * The model + * @param handle + * The name of the link + * @param url + * The URL to add. + */ + static void addUrl(ModelMap model, String handle, URI url) { + model.addAttribute(handle, url); + } + + /** + * Add notice message to model. + * + * @param attrs + * The model + * @param msg + * The notice message to add. + */ + static void addNotice(RedirectAttributes attrs, String msg) { + attrs.addFlashAttribute("notice", msg); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java index c2490ceef5..0363c3c882 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/ReportMailSender.java @@ -1,93 +1,93 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.admin; - -import static java.util.Objects.nonNull; -import static org.slf4j.LoggerFactory.getLogger; -import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT; - -import javax.annotation.PostConstruct; - -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Role; -import org.springframework.mail.MailException; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Component; - -import uk.ac.manchester.spinnaker.alloc.SpallocProperties; -import uk.ac.manchester.spinnaker.alloc.SpallocProperties.ReportProperties; - -/** - * Basic email sending service. - * - * @author Donal Fellows - */ -@Component -@Role(ROLE_SUPPORT) -public class ReportMailSender { - private static final Logger log = getLogger(ReportMailSender.class); - - @Autowired(required = false) - private JavaMailSender emailSender; - - @Autowired - private SpallocProperties properties; - - private ReportProperties props; - - @PostConstruct - private void getProps() { - props = properties.getReportEmail(); - } - - private static boolean haveProp(String propValue) { - return nonNull(propValue) && !propValue.isBlank(); - } - - /** - * Send an assembled message if the service is configured to do so. - *

- * NB: This call may take some time; do not hold a - * transaction open when calling this. - * - * @param email - * The message contents to send. - */ - public void sendServiceMail(Object email) { - if (nonNull(emailSender) && haveProp(props.getTo()) && props.isSend()) { - sendMessage(email.toString()); - } - } - - private void sendMessage(String body) { - var message = new SimpleMailMessage(); - if (haveProp(props.getFrom())) { - message.setFrom(props.getFrom()); - } - message.setTo(props.getTo()); - if (haveProp(props.getSubject())) { - message.setSubject(props.getSubject()); - } - message.setText(body); - try { - emailSender.send(message); - } catch (MailException e) { - log.warn("problem when sending email", e); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.admin; + +import static java.util.Objects.nonNull; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.beans.factory.config.BeanDefinition.ROLE_SUPPORT; + +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Role; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +import uk.ac.manchester.spinnaker.alloc.SpallocProperties; +import uk.ac.manchester.spinnaker.alloc.SpallocProperties.ReportProperties; + +/** + * Basic email sending service. + * + * @author Donal Fellows + */ +@Component +@Role(ROLE_SUPPORT) +public class ReportMailSender { + private static final Logger log = getLogger(ReportMailSender.class); + + @Autowired(required = false) + private JavaMailSender emailSender; + + @Autowired + private SpallocProperties properties; + + private ReportProperties props; + + @PostConstruct + private void getProps() { + props = properties.getReportEmail(); + } + + private static boolean haveProp(String propValue) { + return nonNull(propValue) && !propValue.isBlank(); + } + + /** + * Send an assembled message if the service is configured to do so. + *

+ * NB: This call may take some time; do not hold a + * transaction open when calling this. + * + * @param email + * The message contents to send. + */ + public void sendServiceMail(Object email) { + if (nonNull(emailSender) && haveProp(props.getTo()) && props.isSend()) { + sendMessage(email.toString()); + } + } + + private void sendMessage(String body) { + var message = new SimpleMailMessage(); + if (haveProp(props.getFrom())) { + message.setFrom(props.getFrom()); + } + message.setTo(props.getTo()); + if (haveProp(props.getSubject())) { + message.setSubject(props.getSubject()); + } + message.setText(body); + try { + emailSender.send(message); + } catch (MailException e) { + log.warn("problem when sending email", e); + } + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java index 1fedd7c893..4bc154ba62 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/BlacklistOperation.java @@ -1,31 +1,31 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -/** - * Non-boot operations that may be performed on a BMP. - * - * @author Donal Fellows - */ -public enum BlacklistOperation { - // Careful: values must match SQL (CHECK constraints and queries) - /** Read a blacklist from a board's BMP's flash. */ - READ, - /** Write a blacklist to a board's BMP's flash. */ - WRITE, - /** Read the serial numbers from a board's BMP. */ - GET_SERIAL -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +/** + * Non-boot operations that may be performed on a BMP. + * + * @author Donal Fellows + */ +public enum BlacklistOperation { + // Careful: values must match SQL (CHECK constraints and queries) + /** Read a blacklist from a board's BMP's flash. */ + READ, + /** Write a blacklist to a board's BMP's flash. */ + WRITE, + /** Read the serial numbers from a board's BMP. */ + GET_SERIAL +} 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 1cf3015f26..79b6cf363e 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 @@ -1,201 +1,201 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -import static java.util.EnumSet.noneOf; -import static java.util.Objects.requireNonNull; -import static uk.ac.manchester.spinnaker.alloc.db.Row.enumerate; -import static uk.ac.manchester.spinnaker.alloc.db.Row.integer; -import static uk.ac.manchester.spinnaker.alloc.model.Utils.chip; - -import java.util.HashSet; -import java.util.Optional; - -import org.springframework.dao.DataAccessException; -import org.springframework.stereotype.Component; - -import com.google.errorprone.annotations.RestrictedApi; - -import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAwareBean; -import uk.ac.manchester.spinnaker.machine.Direction; -import uk.ac.manchester.spinnaker.messages.model.Blacklist; - -/** - * Read a blacklist from the database or write it to the database. This works - * with blacklists as a collection of records, not a serialised BLOB. - *

- * Arguably everything in here really ought to be in {@link Blacklist} itself, - * but that's necessarily in code that can't see into the database. - * - * @author Donal Fellows - */ -@Component -public class BlacklistStore extends DatabaseAwareBean { - /** - * Read a blacklist from the database. - * - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - public Optional readBlacklist(int boardId) { - return executeRead(conn -> readBlacklist(conn, boardId)); - } - - /** - * Read a blacklist from the database. - * - * @param conn - * The database connection. - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - private Optional readBlacklist(Connection conn, int boardId) { - try (var blChips = conn.query(GET_BLACKLISTED_CHIPS); - var blCores = conn.query(GET_BLACKLISTED_CORES); - var blLinks = conn.query(GET_BLACKLISTED_LINKS)) { - var blacklistedChips = blChips.call(boardId) - .map(chip("x", "y")).toSet(); - var blacklistedCores = blCores.call(boardId).toCollectingMap( - HashSet::new, chip("x", "y"), integer("p")); - var blacklistedLinks = blLinks.call(boardId).toCollectingMap( - () -> noneOf(Direction.class), chip("x", "y"), - enumerate("direction", Direction.class)); - - if (blacklistedChips.isEmpty() && blacklistedCores.isEmpty() - && blacklistedLinks.isEmpty()) { - return Optional.empty(); - } - return Optional.of(new Blacklist(blacklistedChips, blacklistedCores, - blacklistedLinks)); - } - } - - /** - * Save a blacklist in the database. - * - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - public void writeBlacklist(int boardId, Blacklist blacklist) { - requireNonNull(blacklist); - execute(conn -> { - writeBlacklist(conn, boardId, blacklist); - return this; // dummy - }); - } - - /** - * Save a blacklist in the database. - * - * @param conn - * Which database? - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - private void writeBlacklist(Connection conn, int boardId, - Blacklist blacklist) { - try (var clearChips = conn.update(CLEAR_BLACKLISTED_CHIPS); - var clearCores = conn.update(CLEAR_BLACKLISTED_CORES); - var clearLinks = conn.update(CLEAR_BLACKLISTED_LINKS); - var addChip = conn.update(ADD_BLACKLISTED_CHIP); - var addCore = conn.update(ADD_BLACKLISTED_CORE); - var addLink = conn.update(ADD_BLACKLISTED_LINK)) { - // TODO Keep the old blacklist data where it is the same as before - // Remove the old information - clearChips.call(boardId); - clearCores.call(boardId); - clearLinks.call(boardId); - // Write the new information - blacklist.getChips().forEach(chip -> { - addChip.call(boardId, chip.getX(), chip.getY()); - }); - blacklist.getCores().forEach((chip, cores) -> cores.forEach(c -> { - addCore.call(boardId, chip.getX(), chip.getY(), c); - })); - blacklist.getLinks().forEach((chip, links) -> links.forEach(l -> { - addLink.call(boardId, chip.getX(), chip.getY(), l); - })); - } - } - - /** - * API only exposed for testing purposes. - */ - @ForTestingOnly - interface TestAPI { - /** - * Read a blacklist from the database. - * - * @param conn - * The database connection. - * @param boardId - * The ID of the board. - * @return The blacklist, if one is defined. - * @throws DataAccessException - * If database access fails. - */ - Optional readBlacklist(Connection conn, int boardId); - - /** - * Save a blacklist in the database. - * - * @param conn - * Which database? - * @param boardId - * What board is this a blacklist for? - * @param blacklist - * The blacklist to save. - */ - void writeBlacklist(Connection conn, int boardId, Blacklist blacklist); - } - - /** - * @return The internal API only used for testing. - * @deprecated Only use for testing, as circumvents transaction management. - */ - @Deprecated - @RestrictedApi(explanation = "just for testing", link = "index.html", - allowedOnPath = ".*/src/test/java/.*") - @ForTestingOnly - TestAPI getTestAPI() { - ForTestingOnly.Utils.checkForTestClassOnStack(); - return new TestAPI() { - @Override - public Optional readBlacklist(Connection conn, - int boardId) { - return BlacklistStore.this.readBlacklist(conn, boardId); - } - - @Override - public void writeBlacklist(Connection conn, int boardId, - Blacklist blacklist) { - BlacklistStore.this.writeBlacklist(conn, boardId, blacklist); - } - }; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +import static java.util.EnumSet.noneOf; +import static java.util.Objects.requireNonNull; +import static uk.ac.manchester.spinnaker.alloc.db.Row.enumerate; +import static uk.ac.manchester.spinnaker.alloc.db.Row.integer; +import static uk.ac.manchester.spinnaker.alloc.model.Utils.chip; + +import java.util.HashSet; +import java.util.Optional; + +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Component; + +import com.google.errorprone.annotations.RestrictedApi; + +import uk.ac.manchester.spinnaker.alloc.ForTestingOnly; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAwareBean; +import uk.ac.manchester.spinnaker.machine.Direction; +import uk.ac.manchester.spinnaker.messages.model.Blacklist; + +/** + * Read a blacklist from the database or write it to the database. This works + * with blacklists as a collection of records, not a serialised BLOB. + *

+ * Arguably everything in here really ought to be in {@link Blacklist} itself, + * but that's necessarily in code that can't see into the database. + * + * @author Donal Fellows + */ +@Component +public class BlacklistStore extends DatabaseAwareBean { + /** + * Read a blacklist from the database. + * + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + public Optional readBlacklist(int boardId) { + return executeRead(conn -> readBlacklist(conn, boardId)); + } + + /** + * Read a blacklist from the database. + * + * @param conn + * The database connection. + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + private Optional readBlacklist(Connection conn, int boardId) { + try (var blChips = conn.query(GET_BLACKLISTED_CHIPS); + var blCores = conn.query(GET_BLACKLISTED_CORES); + var blLinks = conn.query(GET_BLACKLISTED_LINKS)) { + var blacklistedChips = blChips.call(boardId) + .map(chip("x", "y")).toSet(); + var blacklistedCores = blCores.call(boardId).toCollectingMap( + HashSet::new, chip("x", "y"), integer("p")); + var blacklistedLinks = blLinks.call(boardId).toCollectingMap( + () -> noneOf(Direction.class), chip("x", "y"), + enumerate("direction", Direction.class)); + + if (blacklistedChips.isEmpty() && blacklistedCores.isEmpty() + && blacklistedLinks.isEmpty()) { + return Optional.empty(); + } + return Optional.of(new Blacklist(blacklistedChips, blacklistedCores, + blacklistedLinks)); + } + } + + /** + * Save a blacklist in the database. + * + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + public void writeBlacklist(int boardId, Blacklist blacklist) { + requireNonNull(blacklist); + execute(conn -> { + writeBlacklist(conn, boardId, blacklist); + return this; // dummy + }); + } + + /** + * Save a blacklist in the database. + * + * @param conn + * Which database? + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + private void writeBlacklist(Connection conn, int boardId, + Blacklist blacklist) { + try (var clearChips = conn.update(CLEAR_BLACKLISTED_CHIPS); + var clearCores = conn.update(CLEAR_BLACKLISTED_CORES); + var clearLinks = conn.update(CLEAR_BLACKLISTED_LINKS); + var addChip = conn.update(ADD_BLACKLISTED_CHIP); + var addCore = conn.update(ADD_BLACKLISTED_CORE); + var addLink = conn.update(ADD_BLACKLISTED_LINK)) { + // TODO Keep the old blacklist data where it is the same as before + // Remove the old information + clearChips.call(boardId); + clearCores.call(boardId); + clearLinks.call(boardId); + // Write the new information + blacklist.getChips().forEach(chip -> { + addChip.call(boardId, chip.getX(), chip.getY()); + }); + blacklist.getCores().forEach((chip, cores) -> cores.forEach(c -> { + addCore.call(boardId, chip.getX(), chip.getY(), c); + })); + blacklist.getLinks().forEach((chip, links) -> links.forEach(l -> { + addLink.call(boardId, chip.getX(), chip.getY(), l); + })); + } + } + + /** + * API only exposed for testing purposes. + */ + @ForTestingOnly + interface TestAPI { + /** + * Read a blacklist from the database. + * + * @param conn + * The database connection. + * @param boardId + * The ID of the board. + * @return The blacklist, if one is defined. + * @throws DataAccessException + * If database access fails. + */ + Optional readBlacklist(Connection conn, int boardId); + + /** + * Save a blacklist in the database. + * + * @param conn + * Which database? + * @param boardId + * What board is this a blacklist for? + * @param blacklist + * The blacklist to save. + */ + void writeBlacklist(Connection conn, int boardId, Blacklist blacklist); + } + + /** + * @return The internal API only used for testing. + * @deprecated Only use for testing, as circumvents transaction management. + */ + @Deprecated + @RestrictedApi(explanation = "just for testing", link = "index.html", + allowedOnPath = ".*/src/test/java/.*") + @ForTestingOnly + TestAPI getTestAPI() { + ForTestingOnly.Utils.checkForTestClassOnStack(); + return new TestAPI() { + @Override + public Optional readBlacklist(Connection conn, + int boardId) { + return BlacklistStore.this.readBlacklist(conn, boardId); + } + + @Override + public void writeBlacklist(Connection conn, int boardId, + Blacklist blacklist) { + BlacklistStore.this.writeBlacklist(conn, boardId, blacklist); + } + }; + } +} 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 c3be794d59..21cff3ee53 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 @@ -1,117 +1,117 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.bmp; - -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 java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; -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; - -/** - * Holds the mapping between physical board IDs and BMP IDs. Physical board IDs - * were allocated by the manufacturer of the boards (Norcott) and are - * only available in source form as labels on the boards. BMP - * identifiers can be read remotely (they come from the LPC17xx In-Application - * Programming entry point's {@code READ_SERIAL_NUMBER} call). - *

- * The original form of blacklists stores them according to their physical board - * ID because that's what is easily available during commissioning. - * - * @author Donal Fellows - */ -@Component -class PhysicalSerialMapping { - private static final Logger log = getLogger(PhysicalSerialMapping.class); - - @Value("classpath:blacklists/spin5-serial.txt") - private Resource spin5serialFile; - - private Map physicalToLogical = new HashMap<>(); - - private Map logicalToPhysical = new HashMap<>(); - - @PostConstruct - void loadMapping() throws IOException { - try (var isr = new InputStreamReader(spin5serialFile.getInputStream(), - UTF_8)) { - buffer(isr).lines().map(s -> s.replaceFirst("#.*", "").strip()) - .filter(not(String::isBlank)) - .forEach(this::parseOneMapping); - } - log.info("loaded physical/logical board ID map: {} entries", - physicalToLogical.size()); - } - - private void parseOneMapping(String line) { - var bits = line.split("\\s+", 2); - if (log.isTraceEnabled()) { - log.trace("parsing line: {}", Arrays.toString(bits)); - } - if (bits.length < 2) { - log.debug("bogus line: {}", line); - return; - } - var physical = bits[0]; - var logical = bits[1]; - var old = physicalToLogical.put(physical, logical); - if (old != null) { - log.warn("replaced mapping for {} (to {}) with {}", physical, old, - logical); - } - old = logicalToPhysical.put(logical, physical); - if (old != null) { - log.warn("replaced mapping for {} (to {}) with {}", logical, old, - physical); - } - } - - /** - * Given a BMP serial identifier, get the physical serial ID for that board. - * - * @param bmpSerialId - * The BMP serial ID. - * @return The physical board identifier, or {@code null} if the BMP serial - * ID is not recognised. - */ - public String getPhysicalId(String bmpSerialId) { - return logicalToPhysical.get(bmpSerialId); - } - - /** - * Given a physical serial identifier, get the BMP serial ID for that board. - * - * @param physicalSerialId - * The physical board serial ID. - * @return The BMP identifier, or {@code null} if the physical board serial - * ID is not recognised. - */ - public String getBMPId(String physicalSerialId) { - return physicalToLogical.get(physicalSerialId); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.bmp; + +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 java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +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; + +/** + * Holds the mapping between physical board IDs and BMP IDs. Physical board IDs + * were allocated by the manufacturer of the boards (Norcott) and are + * only available in source form as labels on the boards. BMP + * identifiers can be read remotely (they come from the LPC17xx In-Application + * Programming entry point's {@code READ_SERIAL_NUMBER} call). + *

+ * The original form of blacklists stores them according to their physical board + * ID because that's what is easily available during commissioning. + * + * @author Donal Fellows + */ +@Component +class PhysicalSerialMapping { + private static final Logger log = getLogger(PhysicalSerialMapping.class); + + @Value("classpath:blacklists/spin5-serial.txt") + private Resource spin5serialFile; + + private Map physicalToLogical = new HashMap<>(); + + private Map logicalToPhysical = new HashMap<>(); + + @PostConstruct + void loadMapping() throws IOException { + try (var isr = new InputStreamReader(spin5serialFile.getInputStream(), + UTF_8)) { + buffer(isr).lines().map(s -> s.replaceFirst("#.*", "").strip()) + .filter(not(String::isBlank)) + .forEach(this::parseOneMapping); + } + log.info("loaded physical/logical board ID map: {} entries", + physicalToLogical.size()); + } + + private void parseOneMapping(String line) { + var bits = line.split("\\s+", 2); + if (log.isTraceEnabled()) { + log.trace("parsing line: {}", Arrays.toString(bits)); + } + if (bits.length < 2) { + log.debug("bogus line: {}", line); + return; + } + var physical = bits[0]; + var logical = bits[1]; + var old = physicalToLogical.put(physical, logical); + if (old != null) { + log.warn("replaced mapping for {} (to {}) with {}", physical, old, + logical); + } + old = logicalToPhysical.put(logical, physical); + if (old != null) { + log.warn("replaced mapping for {} (to {}) with {}", logical, old, + physical); + } + } + + /** + * Given a BMP serial identifier, get the physical serial ID for that board. + * + * @param bmpSerialId + * The BMP serial ID. + * @return The physical board identifier, or {@code null} if the BMP serial + * ID is not recognised. + */ + public String getPhysicalId(String bmpSerialId) { + return logicalToPhysical.get(bmpSerialId); + } + + /** + * Given a physical serial identifier, get the BMP serial ID for that board. + * + * @param physicalSerialId + * The physical board serial ID. + * @return The BMP identifier, or {@code null} if the physical board serial + * ID is not recognised. + */ + public String getBMPId(String physicalSerialId) { + return physicalToLogical.get(physicalSerialId); + } +} 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 418dc3349c..189c506c1c 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 @@ -1,76 +1,76 @@ -/* - * 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 - * - * http://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.compat; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -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; - -/** - * Validates that an argument is a sane value to pass in a classic spalloc API - * call. That means "is it a string, a boolean or a number"? Null is not - * permitted. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = { IsSaneValidator.class }) -public @interface SaneParameter { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad spalloc parameter"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} - -class IsSaneValidator implements ConstraintValidator { - @Override - public boolean isValid(Object value, ConstraintValidatorContext context) { - if (value instanceof String s) { - return !s.isBlank(); - } else { - return (value instanceof Boolean) || (value instanceof Number); - } - } -} +/* + * 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 + * + * http://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.compat; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +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; + +/** + * Validates that an argument is a sane value to pass in a classic spalloc API + * call. That means "is it a string, a boolean or a number"? Null is not + * permitted. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = { IsSaneValidator.class }) +public @interface SaneParameter { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad spalloc parameter"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} + +class IsSaneValidator implements ConstraintValidator { + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + 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/TaskException.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java index 635baded32..0766c3c542 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/TaskException.java @@ -1,32 +1,32 @@ -/* - * 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 - * - * http://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.compat; - -/** - * An exception that a task operation may throw. Such exceptions are converted - * into suitable classic spalloc error response messages by the service message - * handling layer. - * - * @author Donal Fellows - * @see ExceptionResponse - */ -public final class TaskException extends Exception { - private static final long serialVersionUID = 1L; - - TaskException(String msg) { - super(msg); - } -} +/* + * 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 + * + * http://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.compat; + +/** + * An exception that a task operation may throw. Such exceptions are converted + * into suitable classic spalloc error response messages by the service message + * handling layer. + * + * @author Donal Fellows + * @see ExceptionResponse + */ +public final class TaskException extends Exception { + private static final long serialVersionUID = 1L; + + TaskException(String msg) { + super(msg); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java index c49888488f..bebba94adb 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/DatabaseAPI.java @@ -1,649 +1,649 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.db; - -import java.io.File; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import org.springframework.core.io.Resource; -import org.springframework.dao.PermissionDeniedDataAccessException; - -import com.google.errorprone.annotations.CompileTimeConstant; -import com.google.errorprone.annotations.MustBeClosed; - -import uk.ac.manchester.spinnaker.storage.GeneratesID; -import uk.ac.manchester.spinnaker.storage.SingleRowResult; -import uk.ac.manchester.spinnaker.utils.MappableIterable; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * The primary interface to the database. It conceptually represents an SQLite - * database that can have connections opened on it. - * - * @author Donal Fellows - */ -public interface DatabaseAPI { - /** - * Get a connection. This connection is thread-bound and pooled; it must - * not be passed to other threads. They should get their own - * connections instead. The connection has auto-commit disabled; use the - * {@link Connection#transaction(DatabaseEngine.TransactedWithResult) - * transaction()} method instead. - *

- * Note that if an in-memory database is used (see - * {@link #getInMemoryDB()}), that DB can only be accessed from the - * connection returned from this method; the next call to this method - * (whether from the current thread or another one) will get an independent - * database. Such in-memory databases are not subject to thread-bound - * cleanup actions; they're simply deleted from memory when no longer used - * (but the connection should be {@code close()}d after use for efficiency - * nonetheless). - *

- * This would be marked with {@link MustBeClosed} except that causes a mess - * elsewhere. - * - * @return A configured initialised connection to the database. - */ - @MustBeClosed - Connection getConnection(); - - /** - * Create an engine interface for an in-memory database. This is intended - * mainly for testing purposes. Note that various coupled automatic services - * are disabled, in particular connections are not closed automatically. - * - * @return The in-memory database interface. - */ - DatabaseAPI getInMemoryDB(); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. - * - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be held - * at once, but only one write lock. Locks cannot be - * upgraded (because that causes deadlocks). - * @param operation - * The operation to run - * @throws RuntimeException - * If something goes wrong with the database access or the - * contained code. - */ - void executeVoid(boolean lockForWriting, Connected operation); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. This uses a write lock. - * - * @param operation - * The operation to run - * @throws RuntimeException - * If something goes wrong with the database access or the - * contained code. - */ - default void executeVoid(Connected operation) { - executeVoid(true, operation); - } - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. - * - * @param - * The type of the result of {@code operation} - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be held - * at once, but only one write lock. Locks cannot be - * upgraded (because that causes deadlocks). - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @throws RuntimeException - * If something other than database access goes wrong with the - * contained code. - */ - T execute(boolean lockForWriting, ConnectedWithResult operation); - - /** - * A connection manager and transaction runner. If the {@code operation} - * completes normally (and this isn't a nested use), the transaction - * commits. If an exception is thrown, the transaction is rolled back. The - * connection is closed up in any case. This uses a write lock. - * - * @param - * The type of the result of {@code operation} - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @throws RuntimeException - * If something other than database access goes wrong with the - * contained code. - */ - default T execute(ConnectedWithResult operation) { - return execute(true, operation); - } - - /** - * Creates a backup of the database. This operation should only be - * called by administrators. - * - * @param backupFilename - * The backup file to create. - */ - void createBackup(File backupFilename); - - /** - * Restores the database from backup. This operation should only be - * called by administrators. - * - * @param backupFilename - * The backup file to restore from. - * @throws PermissionDeniedDataAccessException - * If the backup cannot be read. - */ - void restoreFromBackup(File backupFilename); - - /** - * Connections made by the database engine bean. Its methods do not throw - * checked exceptions. The connection is thread-bound, and will be cleaned - * up correctly when the thread exits (ideal for thread pools). - */ - interface Connection extends AutoCloseable { - /** - * Closes this connection and releases any resources. The actual - * underlying connection may remain open if the connection pool wishes - * to maintain it, but this handle should not be retained by the caller - * after this point. - * - * @see java.sql.Connection#close() - */ - @Override - void close(); - - /** - * Undoes all changes made in the current transaction and releases any - * database locks currently held by this connection. - *

- * This method should be used only when in a transaction; it is only - * required when the transaction is to be rolled back without throwing - * an exception, as the normal behaviour of the internal transaction - * manager is to roll the transaction back when an exception leaves the - * code inside the transaction boundary. - * - * @see java.sql.Connection#rollback() - */ - void rollback(); - - /** - * Retrieves whether this connection is in read-only mode. - * - * @return {@code true} if this connection is read-only; {@code false} - * otherwise. - * @see java.sql.Connection#isReadOnly() - */ - boolean isReadOnly(); - - /** - * Whether the historical data DB is available. If it isn't, you can't - * move any data to longer-term storage, but ordinary operations should - * be fine. - * - * @return Whether the historical data DB is available. - */ - boolean isHistoricalDBAvailable(); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. - * - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be - * held at once, but only one write lock. Locks - * cannot be upgraded (because that causes - * deadlocks). - * @param operation - * The operation to run - * @see #transaction(DatabaseEngine.TransactedWithResult) - */ - void transaction(boolean lockForWriting, Transacted operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. This uses a - * write lock. - * - * @param operation - * The operation to run - * @see #transaction(DatabaseEngine.TransactedWithResult) - */ - void transaction(Transacted operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. This uses a - * write lock. - * - * @param - * The type of the result of {@code operation} - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @see #transaction(DatabaseEngine.Transacted) - */ - T transaction(TransactedWithResult operation); - - /** - * A nestable transaction runner. If the {@code operation} completes - * normally (and this isn't a nested use), the transaction commits. If - * an exception is thrown, the transaction is rolled back. - * - * @param - * The type of the result of {@code operation} - * @param lockForWriting - * Whether to lock for writing. Multiple read locks can be - * held at once, but only one write lock. Locks - * cannot be upgraded (because that causes - * deadlocks). - * @param operation - * The operation to run - * @return the value returned by {@code operation} - * @see #transaction(DatabaseEngine.Transacted) - */ - T transaction(boolean lockForWriting, - TransactedWithResult operation); - - // @formatter:off - /** - * Create a new query. Usage pattern: - *

-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sql - * The SQL of the query. - * @return The query object. - * @see #query(Resource) - * @see #update(String) - * @see SQLQueries - */ - // @formatter:on - Query query(@CompileTimeConstant String sql); - - // @formatter:off - /** - * Create a new query. Usage pattern: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(SQL_SELECT)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sql - * The SQL of the query. - * @param lockType - * Whether we expect to have a write lock. This is vital - * @return The query object. - * @see #query(Resource) - * @see #update(String) - * @see SQLQueries - */ - // @formatter:on - Query query(@CompileTimeConstant String sql, boolean lockType); - - // @formatter:off - /** - * Create a new query. - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sqlResource - * Reference to the SQL of the query. - * @return The query object. - * @see #query(String) - * @see #update(Resource) - * @see SQLQueries - */ - // @formatter:on - Query query(Resource sqlResource); - - // @formatter:off - /** - * Create a new query. - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     for (var row : u.call(argument1, argument2)) {
-		 *         // Do something with the row
-		 *     }
-		 * }
-		 * 
- * or: - *
-		 * try (var q = conn.query(sqlSelectResource)) {
-		 *     u.call(argument1, argument2).forEach(row -> {
-		 *         // Do something with the row
-		 *     });
-		 * }
-		 * 
- * - * @param sqlResource - * Reference to the SQL of the query. - * @param lockType - * Whether we expect to have a write lock. This is vital - * only when the query is an {@code UPDATE RETURNING}. - * @return The query object. - * @see #query(String) - * @see #update(Resource) - * @see SQLQueries - */ - // @formatter:on - Query query(Resource sqlResource, boolean lockType); - - // @formatter:off - /** - * Create a new update. Usage pattern: - *
-		 * try (var u = conn.update(SQL_UPDATE)) {
-		 *     int numRows = u.call(argument1, argument2);
-		 * }
-		 * 
- * or: - *
-		 * try (var u = conn.update(SQL_INSERT)) {
-		 *     for (var key : u.keys(argument1, argument2)) {
-		 *         // Do something with the key
-		 *     }
-		 * }
-		 * 
- * or even: - *
-		 * try (var u = conn.update(SQL_INSERT)) {
-		 *     u.key(argument1, argument2).ifPresent(key -> {
-		 *         // Do something with the key
-		 *     });
-		 * }
-		 * 
- *

- * Note: If you use a {@code RETURNING} clause then - * you should use a {@link Query} with the {@code lockType} set to - * {@code true}. - * - * @param sql - * The SQL of the update. - * @return The update object. - * @see #update(Resource) - * @see #query(String) - * @see SQLQueries - */ - // @formatter:on - Update update(@CompileTimeConstant String sql); - - // @formatter:off - /** - * Create a new update. - *

-		 * try (var u = conn.update(sqlUpdateResource)) {
-		 *     int numRows = u.call(argument1, argument2);
-		 * }
-		 * 
- * or: - *
-		 * try (var u = conn.update(sqlInsertResource)) {
-		 *     for (var key : u.keys(argument1, argument2)) {
-		 *         // Do something with the key
-		 *     }
-		 * }
-		 * 
- * or even: - *
-		 * try (var u = conn.update(sqlInsertResource)) {
-		 *     u.key(argument1, argument2).ifPresent(key -> {
-		 *         // Do something with the key
-		 *     });
-		 * }
-		 * 
- *

- * Note: If you use a {@code RETURNING} clause then - * you should use a {@link Query} with the {@code lockType} set to - * {@code true}. - * - * @param sqlResource - * Reference to the SQL of the update. - * @return The update object. - * @see #update(String) - * @see #query(Resource) - * @see SQLQueries - */ - // @formatter:on - Update update(Resource sqlResource); - } - - /** - * Some code that may be run within a transaction. - */ - @FunctionalInterface - interface Transacted { - /** - * The operation to run. - */ - void act(); - } - - /** - * Some code that may be run within a transaction that returns a result. - * - * @param - * The type of the result of the code. - */ - @FunctionalInterface - interface TransactedWithResult { - /** - * The operation to run. - * - * @return The result of the operation. - */ - T act(); - } - - /** - * Some code that may be run within a transaction and which will be given a - * new connection for the duration. - */ - @FunctionalInterface - interface Connected { - /** - * The operation to run. - * - * @param connection - * The newly-created connection. Do not save beyond the scope - * of this action. - */ - void act(Connection connection); - } - - /** - * Some code that may be run within a transaction that returns a result and - * which will be given a new connection for the duration. - * - * @param - * The type of the result of the code. - */ - @FunctionalInterface - interface ConnectedWithResult { - /** - * The operation to run. - * - * @param connection - * The newly-created connection. Do not save beyond the scope - * of this action. - * @return The result of the operation. - */ - T act(Connection connection); - } - - /** - * Common shared API between {@link Query} and {@link Update}. - * - * @author Donal Fellows - */ - interface StatementCommon extends AutoCloseable { - /** - * Get the number of arguments expected when calling this statement. - * - * @return The number of arguments. Types are arbitrary (because SQLite) - */ - int getNumArguments(); - - /** - * Get the set of names of columns produced when calling this statement. - * - * @return A set of names. The order is the order in the SQL producing - * the result set, but this should normally be insignificant. - */ - Set getRowColumnNames(); - - /** - * Close this statement. This never throws a checked exception. - */ - @Override - void close(); - - /** - * Get the query plan explanation. Note that DML and DDL may - * have empty query plans; that's up to the DB. - * - * @return A list of lines that describe the query plan. - * @see SQLite - * documentation - */ - List explainQueryPlan(); - } - - /** - * Wrapping a prepared query to be more suitable for Java 8 onwards. - * - * @author Donal Fellows - */ - interface Query extends StatementCommon { - /** - * Run the query on the given arguments. - * - * @param arguments - * Positional argument to the query - * @return The results, wrapped as a one-shot iterable. The - * {@linkplain Row rows} in the iterable must not be - * retained by callers; they may share state and might not - * outlive the iteration. - */ - MappableIterable call(Object... arguments); - - /** - * Run the query on the given arguments. The query must be one that only - * produces a single row result. - * - * @param arguments - * Positional argument to the query - * @return The single row with the results, or empty if there is no such - * row. - * @see SingleRowResult - */ - Optional call1(Object... arguments); - } - - /** - * Wrapping a prepared update to be more suitable for Java 8 onwards. - * - * @author Donal Fellows - */ - @UsedInJavadocOnly(GeneratesID.class) - interface Update extends StatementCommon { - /** - * Run the update on the given arguments. - * - * @param arguments - * Positional argument to the query - * @return The number of rows updated - */ - int call(Object... arguments); - - /** - * Run the update on the given arguments. - * - * @param arguments - * Positional arguments to the query - * @return The integer primary keys generated by the update. - * @see GeneratesID - */ - MappableIterable keys(Object... arguments); - - /** - * Run the update on the given arguments. This is expected to generate a - * single integer primary key (common with {@code INSERT}). - * - * @param arguments - * Positional arguments to the query - * @return The integer primary key generated by the update. - * @see GeneratesID - */ - Optional key(Object... arguments); - } -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.db; + +import java.io.File; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.springframework.core.io.Resource; +import org.springframework.dao.PermissionDeniedDataAccessException; + +import com.google.errorprone.annotations.CompileTimeConstant; +import com.google.errorprone.annotations.MustBeClosed; + +import uk.ac.manchester.spinnaker.storage.GeneratesID; +import uk.ac.manchester.spinnaker.storage.SingleRowResult; +import uk.ac.manchester.spinnaker.utils.MappableIterable; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * The primary interface to the database. It conceptually represents an SQLite + * database that can have connections opened on it. + * + * @author Donal Fellows + */ +public interface DatabaseAPI { + /** + * Get a connection. This connection is thread-bound and pooled; it must + * not be passed to other threads. They should get their own + * connections instead. The connection has auto-commit disabled; use the + * {@link Connection#transaction(DatabaseEngine.TransactedWithResult) + * transaction()} method instead. + *

+ * Note that if an in-memory database is used (see + * {@link #getInMemoryDB()}), that DB can only be accessed from the + * connection returned from this method; the next call to this method + * (whether from the current thread or another one) will get an independent + * database. Such in-memory databases are not subject to thread-bound + * cleanup actions; they're simply deleted from memory when no longer used + * (but the connection should be {@code close()}d after use for efficiency + * nonetheless). + *

+ * This would be marked with {@link MustBeClosed} except that causes a mess + * elsewhere. + * + * @return A configured initialised connection to the database. + */ + @MustBeClosed + Connection getConnection(); + + /** + * Create an engine interface for an in-memory database. This is intended + * mainly for testing purposes. Note that various coupled automatic services + * are disabled, in particular connections are not closed automatically. + * + * @return The in-memory database interface. + */ + DatabaseAPI getInMemoryDB(); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. + * + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be held + * at once, but only one write lock. Locks cannot be + * upgraded (because that causes deadlocks). + * @param operation + * The operation to run + * @throws RuntimeException + * If something goes wrong with the database access or the + * contained code. + */ + void executeVoid(boolean lockForWriting, Connected operation); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. This uses a write lock. + * + * @param operation + * The operation to run + * @throws RuntimeException + * If something goes wrong with the database access or the + * contained code. + */ + default void executeVoid(Connected operation) { + executeVoid(true, operation); + } + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. + * + * @param + * The type of the result of {@code operation} + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be held + * at once, but only one write lock. Locks cannot be + * upgraded (because that causes deadlocks). + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @throws RuntimeException + * If something other than database access goes wrong with the + * contained code. + */ + T execute(boolean lockForWriting, ConnectedWithResult operation); + + /** + * A connection manager and transaction runner. If the {@code operation} + * completes normally (and this isn't a nested use), the transaction + * commits. If an exception is thrown, the transaction is rolled back. The + * connection is closed up in any case. This uses a write lock. + * + * @param + * The type of the result of {@code operation} + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @throws RuntimeException + * If something other than database access goes wrong with the + * contained code. + */ + default T execute(ConnectedWithResult operation) { + return execute(true, operation); + } + + /** + * Creates a backup of the database. This operation should only be + * called by administrators. + * + * @param backupFilename + * The backup file to create. + */ + void createBackup(File backupFilename); + + /** + * Restores the database from backup. This operation should only be + * called by administrators. + * + * @param backupFilename + * The backup file to restore from. + * @throws PermissionDeniedDataAccessException + * If the backup cannot be read. + */ + void restoreFromBackup(File backupFilename); + + /** + * Connections made by the database engine bean. Its methods do not throw + * checked exceptions. The connection is thread-bound, and will be cleaned + * up correctly when the thread exits (ideal for thread pools). + */ + interface Connection extends AutoCloseable { + /** + * Closes this connection and releases any resources. The actual + * underlying connection may remain open if the connection pool wishes + * to maintain it, but this handle should not be retained by the caller + * after this point. + * + * @see java.sql.Connection#close() + */ + @Override + void close(); + + /** + * Undoes all changes made in the current transaction and releases any + * database locks currently held by this connection. + *

+ * This method should be used only when in a transaction; it is only + * required when the transaction is to be rolled back without throwing + * an exception, as the normal behaviour of the internal transaction + * manager is to roll the transaction back when an exception leaves the + * code inside the transaction boundary. + * + * @see java.sql.Connection#rollback() + */ + void rollback(); + + /** + * Retrieves whether this connection is in read-only mode. + * + * @return {@code true} if this connection is read-only; {@code false} + * otherwise. + * @see java.sql.Connection#isReadOnly() + */ + boolean isReadOnly(); + + /** + * Whether the historical data DB is available. If it isn't, you can't + * move any data to longer-term storage, but ordinary operations should + * be fine. + * + * @return Whether the historical data DB is available. + */ + boolean isHistoricalDBAvailable(); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. + * + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be + * held at once, but only one write lock. Locks + * cannot be upgraded (because that causes + * deadlocks). + * @param operation + * The operation to run + * @see #transaction(DatabaseEngine.TransactedWithResult) + */ + void transaction(boolean lockForWriting, Transacted operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. This uses a + * write lock. + * + * @param operation + * The operation to run + * @see #transaction(DatabaseEngine.TransactedWithResult) + */ + void transaction(Transacted operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. This uses a + * write lock. + * + * @param + * The type of the result of {@code operation} + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @see #transaction(DatabaseEngine.Transacted) + */ + T transaction(TransactedWithResult operation); + + /** + * A nestable transaction runner. If the {@code operation} completes + * normally (and this isn't a nested use), the transaction commits. If + * an exception is thrown, the transaction is rolled back. + * + * @param + * The type of the result of {@code operation} + * @param lockForWriting + * Whether to lock for writing. Multiple read locks can be + * held at once, but only one write lock. Locks + * cannot be upgraded (because that causes + * deadlocks). + * @param operation + * The operation to run + * @return the value returned by {@code operation} + * @see #transaction(DatabaseEngine.Transacted) + */ + T transaction(boolean lockForWriting, + TransactedWithResult operation); + + // @formatter:off + /** + * Create a new query. Usage pattern: + *

+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sql + * The SQL of the query. + * @return The query object. + * @see #query(Resource) + * @see #update(String) + * @see SQLQueries + */ + // @formatter:on + Query query(@CompileTimeConstant String sql); + + // @formatter:off + /** + * Create a new query. Usage pattern: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(SQL_SELECT)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sql + * The SQL of the query. + * @param lockType + * Whether we expect to have a write lock. This is vital + * @return The query object. + * @see #query(Resource) + * @see #update(String) + * @see SQLQueries + */ + // @formatter:on + Query query(@CompileTimeConstant String sql, boolean lockType); + + // @formatter:off + /** + * Create a new query. + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sqlResource + * Reference to the SQL of the query. + * @return The query object. + * @see #query(String) + * @see #update(Resource) + * @see SQLQueries + */ + // @formatter:on + Query query(Resource sqlResource); + + // @formatter:off + /** + * Create a new query. + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     for (var row : u.call(argument1, argument2)) {
+		 *         // Do something with the row
+		 *     }
+		 * }
+		 * 
+ * or: + *
+		 * try (var q = conn.query(sqlSelectResource)) {
+		 *     u.call(argument1, argument2).forEach(row -> {
+		 *         // Do something with the row
+		 *     });
+		 * }
+		 * 
+ * + * @param sqlResource + * Reference to the SQL of the query. + * @param lockType + * Whether we expect to have a write lock. This is vital + * only when the query is an {@code UPDATE RETURNING}. + * @return The query object. + * @see #query(String) + * @see #update(Resource) + * @see SQLQueries + */ + // @formatter:on + Query query(Resource sqlResource, boolean lockType); + + // @formatter:off + /** + * Create a new update. Usage pattern: + *
+		 * try (var u = conn.update(SQL_UPDATE)) {
+		 *     int numRows = u.call(argument1, argument2);
+		 * }
+		 * 
+ * or: + *
+		 * try (var u = conn.update(SQL_INSERT)) {
+		 *     for (var key : u.keys(argument1, argument2)) {
+		 *         // Do something with the key
+		 *     }
+		 * }
+		 * 
+ * or even: + *
+		 * try (var u = conn.update(SQL_INSERT)) {
+		 *     u.key(argument1, argument2).ifPresent(key -> {
+		 *         // Do something with the key
+		 *     });
+		 * }
+		 * 
+ *

+ * Note: If you use a {@code RETURNING} clause then + * you should use a {@link Query} with the {@code lockType} set to + * {@code true}. + * + * @param sql + * The SQL of the update. + * @return The update object. + * @see #update(Resource) + * @see #query(String) + * @see SQLQueries + */ + // @formatter:on + Update update(@CompileTimeConstant String sql); + + // @formatter:off + /** + * Create a new update. + *

+		 * try (var u = conn.update(sqlUpdateResource)) {
+		 *     int numRows = u.call(argument1, argument2);
+		 * }
+		 * 
+ * or: + *
+		 * try (var u = conn.update(sqlInsertResource)) {
+		 *     for (var key : u.keys(argument1, argument2)) {
+		 *         // Do something with the key
+		 *     }
+		 * }
+		 * 
+ * or even: + *
+		 * try (var u = conn.update(sqlInsertResource)) {
+		 *     u.key(argument1, argument2).ifPresent(key -> {
+		 *         // Do something with the key
+		 *     });
+		 * }
+		 * 
+ *

+ * Note: If you use a {@code RETURNING} clause then + * you should use a {@link Query} with the {@code lockType} set to + * {@code true}. + * + * @param sqlResource + * Reference to the SQL of the update. + * @return The update object. + * @see #update(String) + * @see #query(Resource) + * @see SQLQueries + */ + // @formatter:on + Update update(Resource sqlResource); + } + + /** + * Some code that may be run within a transaction. + */ + @FunctionalInterface + interface Transacted { + /** + * The operation to run. + */ + void act(); + } + + /** + * Some code that may be run within a transaction that returns a result. + * + * @param + * The type of the result of the code. + */ + @FunctionalInterface + interface TransactedWithResult { + /** + * The operation to run. + * + * @return The result of the operation. + */ + T act(); + } + + /** + * Some code that may be run within a transaction and which will be given a + * new connection for the duration. + */ + @FunctionalInterface + interface Connected { + /** + * The operation to run. + * + * @param connection + * The newly-created connection. Do not save beyond the scope + * of this action. + */ + void act(Connection connection); + } + + /** + * Some code that may be run within a transaction that returns a result and + * which will be given a new connection for the duration. + * + * @param + * The type of the result of the code. + */ + @FunctionalInterface + interface ConnectedWithResult { + /** + * The operation to run. + * + * @param connection + * The newly-created connection. Do not save beyond the scope + * of this action. + * @return The result of the operation. + */ + T act(Connection connection); + } + + /** + * Common shared API between {@link Query} and {@link Update}. + * + * @author Donal Fellows + */ + interface StatementCommon extends AutoCloseable { + /** + * Get the number of arguments expected when calling this statement. + * + * @return The number of arguments. Types are arbitrary (because SQLite) + */ + int getNumArguments(); + + /** + * Get the set of names of columns produced when calling this statement. + * + * @return A set of names. The order is the order in the SQL producing + * the result set, but this should normally be insignificant. + */ + Set getRowColumnNames(); + + /** + * Close this statement. This never throws a checked exception. + */ + @Override + void close(); + + /** + * Get the query plan explanation. Note that DML and DDL may + * have empty query plans; that's up to the DB. + * + * @return A list of lines that describe the query plan. + * @see SQLite + * documentation + */ + List explainQueryPlan(); + } + + /** + * Wrapping a prepared query to be more suitable for Java 8 onwards. + * + * @author Donal Fellows + */ + interface Query extends StatementCommon { + /** + * Run the query on the given arguments. + * + * @param arguments + * Positional argument to the query + * @return The results, wrapped as a one-shot iterable. The + * {@linkplain Row rows} in the iterable must not be + * retained by callers; they may share state and might not + * outlive the iteration. + */ + MappableIterable call(Object... arguments); + + /** + * Run the query on the given arguments. The query must be one that only + * produces a single row result. + * + * @param arguments + * Positional argument to the query + * @return The single row with the results, or empty if there is no such + * row. + * @see SingleRowResult + */ + Optional call1(Object... arguments); + } + + /** + * Wrapping a prepared update to be more suitable for Java 8 onwards. + * + * @author Donal Fellows + */ + @UsedInJavadocOnly(GeneratesID.class) + interface Update extends StatementCommon { + /** + * Run the update on the given arguments. + * + * @param arguments + * Positional argument to the query + * @return The number of rows updated + */ + int call(Object... arguments); + + /** + * Run the update on the given arguments. + * + * @param arguments + * Positional arguments to the query + * @return The integer primary keys generated by the update. + * @see GeneratesID + */ + MappableIterable keys(Object... arguments); + + /** + * Run the update on the given arguments. This is expected to generate a + * single integer primary key (common with {@code INSERT}). + * + * @param arguments + * Positional arguments to the query + * @return The integer primary key generated by the update. + * @see GeneratesID + */ + Optional key(Object... arguments); + } +} 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 86812d9433..71a25ea28d 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 @@ -848,7 +848,7 @@ JOIN boards USING (board_id) @SingleRowResult protected static final String COUNT_PENDING_CHANGES = """ SELECT count(*) AS c - FROM pending_changes + FROM pending_changes """; /** @@ -1473,7 +1473,7 @@ JOIN groups USING (group_id) JOIN user_info USING (user_id) JOIN groups USING (group_id) WHERE membership_id = :membership_id - LIMIT 1 + LIMIT 1 """; /** 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 index e46450cef7..362110ba22 100644 --- 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 @@ -1,40 +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 - * - * http://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; -} +/* + * 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 + * + * http://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/Utils.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java index 560c2f5f6e..0df05f40b9 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/model/Utils.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2022 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 - * - * http://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 java.util.function.Function; - -import uk.ac.manchester.spinnaker.alloc.db.Row; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** Miscellaneous utilities. */ -public abstract class Utils { - private Utils() { - } - - /** - * Extract a chip from a result set row. - * - * @param row - * The row to extract from. - * @param x - * The name of the column with the X coordinate. - * @param y - * The name of the column with the Y coordinate. - * @return The chip location. - */ - public static ChipLocation chip(Row row, String x, String y) { - return new ChipLocation(row.getInt(x), row.getInt(y)); - } - - /** - * Create a function for extracting a chip from a result set row. - * - * @param x - * The name of the column with the X coordinate. - * @param y - * The name of the column with the Y coordinate. - * @return The mapping function. - */ - public static Function chip(String x, String y) { - return row -> new ChipLocation(row.getInt(x), row.getInt(y)); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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 java.util.function.Function; + +import uk.ac.manchester.spinnaker.alloc.db.Row; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** Miscellaneous utilities. */ +public abstract class Utils { + private Utils() { + } + + /** + * Extract a chip from a result set row. + * + * @param row + * The row to extract from. + * @param x + * The name of the column with the X coordinate. + * @param y + * The name of the column with the Y coordinate. + * @return The chip location. + */ + public static ChipLocation chip(Row row, String x, String y) { + return new ChipLocation(row.getInt(x), row.getInt(y)); + } + + /** + * Create a function for extracting a chip from a result set row. + * + * @param x + * The name of the column with the X coordinate. + * @param y + * The name of the column with the Y coordinate. + * @return The mapping function. + */ + public static Function chip(String x, String y) { + return row -> new ChipLocation(row.getInt(x), row.getInt(y)); + } +} diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java index fd271f8484..1d68e38725 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/OpenIDUserAware.java @@ -1,100 +1,100 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.security; - -import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SUB; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL_VERIFIED; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.NAME; -import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME; - -import java.util.Objects; -import java.util.Optional; - -import org.springframework.security.oauth2.core.user.OAuth2User; - -/** - * An object that can say something about what user it was derived from. Note - * that you never have both the user information and the token at the same time, - * but they contain fairly similar contents. - */ -public interface OpenIDUserAware { - /** - * Get the underlying OpenID user information. - * - * @return The user info, if known. Pay attention to the attributes. - */ - Optional getOpenIdUser(); - - /** - * Get a claim/attribute that is a string. - * - * @param claimName - * The name of the claim. - * @return The string. - * @throws IllegalStateException - * If {@link #getOpenIdUser()} doesn't provide anything we can - * get claims from. - */ - default String getStringClaim(String claimName) { - return getOpenIdUser() - .map(u -> Objects.toString(u.getAttribute(claimName))) - .orElseThrow(() -> new IllegalStateException( - "no user or token to supply claim")); - } - - /** - * @return The OpenID subject identifier. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdSubject() { - return getStringClaim(SUB); - } - - /** - * @return The preferred OpenID user name. We don't use this - * directly as it may clash with other user names. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdUserName() { - return getStringClaim(PREFERRED_USERNAME); - } - - /** - * @return The real name of the OpenID user. - * @throws IllegalStateException - * If the object was made without either a user or a token. - */ - default String getOpenIdName() { - return getStringClaim(NAME); - } - - /** - * @return The verified email address of the OpenID user, if available. - */ - default Optional getOpenIdEmail() { - var email = getOpenIdUser().map(uu -> uu.getAttributes()) - .filter(uu -> uu.containsKey(EMAIL_VERIFIED) - && (Boolean) uu.get(EMAIL_VERIFIED)) - .map(uu -> uu.get(EMAIL).toString()); - if (email.isPresent()) { - return email; - } - return null; - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.security; + +import static org.springframework.security.oauth2.core.oidc.IdTokenClaimNames.SUB; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.EMAIL_VERIFIED; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.NAME; +import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME; + +import java.util.Objects; +import java.util.Optional; + +import org.springframework.security.oauth2.core.user.OAuth2User; + +/** + * An object that can say something about what user it was derived from. Note + * that you never have both the user information and the token at the same time, + * but they contain fairly similar contents. + */ +public interface OpenIDUserAware { + /** + * Get the underlying OpenID user information. + * + * @return The user info, if known. Pay attention to the attributes. + */ + Optional getOpenIdUser(); + + /** + * Get a claim/attribute that is a string. + * + * @param claimName + * The name of the claim. + * @return The string. + * @throws IllegalStateException + * If {@link #getOpenIdUser()} doesn't provide anything we can + * get claims from. + */ + default String getStringClaim(String claimName) { + return getOpenIdUser() + .map(u -> Objects.toString(u.getAttribute(claimName))) + .orElseThrow(() -> new IllegalStateException( + "no user or token to supply claim")); + } + + /** + * @return The OpenID subject identifier. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdSubject() { + return getStringClaim(SUB); + } + + /** + * @return The preferred OpenID user name. We don't use this + * directly as it may clash with other user names. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdUserName() { + return getStringClaim(PREFERRED_USERNAME); + } + + /** + * @return The real name of the OpenID user. + * @throws IllegalStateException + * If the object was made without either a user or a token. + */ + default String getOpenIdName() { + return getStringClaim(NAME); + } + + /** + * @return The verified email address of the OpenID user, if available. + */ + default Optional getOpenIdEmail() { + var email = getOpenIdUser().map(uu -> uu.getAttributes()) + .filter(uu -> uu.containsKey(EMAIL_VERIFIED) + && (Boolean) uu.get(EMAIL_VERIFIED)) + .map(uu -> uu.get(EMAIL).toString()); + if (email.isPresent()) { + return email; + } + return null; + } +} diff --git a/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json index b528a414f6..2e45818e2a 100644 --- a/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/SpiNNaker-allocserv/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -15,4 +15,4 @@ "description": "Comma-separated list (in a string) of package names to scan." } ] -} \ No newline at end of file +} 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 29cb17de69..eecbddcfd4 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 @@ -1,225 +1,225 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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; - -import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; -import uk.ac.manchester.spinnaker.storage.GeneratesID; -import uk.ac.manchester.spinnaker.storage.Parameter; -import uk.ac.manchester.spinnaker.storage.ResultColumn; -import uk.ac.manchester.spinnaker.storage.SingleRowResult; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * SQL queries for testing purposes. - * - * @see SQLQueries - */ -@UsedInJavadocOnly(SQLQueries.class) -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 (?, ?) - """; - - /** 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 (?, ?, ?, ?) - """; - - /** 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 (?, ?) - """; - - /** Count the jobs. */ - @ResultColumn("cnt") - @SingleRowResult - 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 - """; - - /** Count the active power change requests. */ - @ResultColumn("cnt") - @SingleRowResult - String TEST_COUNT_POWER_CHANGES = """ - SELECT COUNT(*) AS cnt - FROM pending_changes - """; - - /** 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 - """; - - /** 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 - """; - - /** 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 machine_id = ? AND user_id = ? - """; - - /** Set the quota for a group. */ - @Parameter("quota") - @Parameter("group") - String TEST_SET_QUOTA = """ - UPDATE groups - SET quota = :quota - WHERE group_id = :group - """; - - /** Create a machine, specifying the ID. */ - @Parameter("machine_id") - @Parameter("machine_name") - @Parameter("width") - @Parameter("height") - @Parameter("depth") - @GeneratesID - String INSERT_MACHINE = """ - INSERT OR IGNORE INTO machines( - machine_id, machine_name, width, height, [depth], board_model) - VALUES (?, ?, ?, ?, ?, 5) - """; - - /** Create a BMP, specifying the ID. */ - @Parameter("bmp_id") - @Parameter("machine_id") - @Parameter("address") - @Parameter("cabinet") - @Parameter("frame") - @GeneratesID - String INSERT_BMP_WITH_ID = """ - INSERT OR IGNORE INTO bmp( - bmp_id, machine_id, address, cabinet, frame) - VALUES (?, ?, ?, ?, ?) - """; - - /** Create a user, specifying the ID. */ - @Parameter("user_id") - @Parameter("user_name") - @Parameter("trust_level") - @Parameter("disabled") - @GeneratesID - String INSERT_USER = """ - INSERT OR IGNORE 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 OR IGNORE INTO 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 OR IGNORE INTO group_memberships( - membership_id, user_id, group_id) - VALUES (?, ?, ?) - """; - - /** Create a board, specifying the ID. */ - @Parameter("board_id") - @Parameter("address") - @Parameter("bmp_id") - @Parameter("board_num") - @Parameter("machine_id") - @Parameter("x") - @Parameter("y") - @Parameter("z") - @Parameter("root_x") - @Parameter("root_y") - @Parameter("board_power") - @GeneratesID - String INSERT_BOARD_WITH_ID = """ - INSERT OR IGNORE 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") - @Parameter("owner") - @Parameter("group_id") - @Parameter("root_id") - @Parameter("job_state") - @Parameter("create_timestamp") - @Parameter("allocation_timestamp") - @Parameter("death_timestamp") - @Parameter("allocation_size") - @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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """; -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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; + +import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; +import uk.ac.manchester.spinnaker.storage.GeneratesID; +import uk.ac.manchester.spinnaker.storage.Parameter; +import uk.ac.manchester.spinnaker.storage.ResultColumn; +import uk.ac.manchester.spinnaker.storage.SingleRowResult; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * SQL queries for testing purposes. + * + * @see SQLQueries + */ +@UsedInJavadocOnly(SQLQueries.class) +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 (?, ?) + """; + + /** 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 (?, ?, ?, ?) + """; + + /** 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 (?, ?) + """; + + /** Count the jobs. */ + @ResultColumn("cnt") + @SingleRowResult + 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 + """; + + /** Count the active power change requests. */ + @ResultColumn("cnt") + @SingleRowResult + String TEST_COUNT_POWER_CHANGES = """ + SELECT COUNT(*) AS cnt + FROM pending_changes + """; + + /** 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 + """; + + /** 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 + """; + + /** 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 machine_id = ? AND user_id = ? + """; + + /** Set the quota for a group. */ + @Parameter("quota") + @Parameter("group") + String TEST_SET_QUOTA = """ + UPDATE groups + SET quota = :quota + WHERE group_id = :group + """; + + /** Create a machine, specifying the ID. */ + @Parameter("machine_id") + @Parameter("machine_name") + @Parameter("width") + @Parameter("height") + @Parameter("depth") + @GeneratesID + String INSERT_MACHINE = """ + INSERT OR IGNORE INTO machines( + machine_id, machine_name, width, height, [depth], board_model) + VALUES (?, ?, ?, ?, ?, 5) + """; + + /** Create a BMP, specifying the ID. */ + @Parameter("bmp_id") + @Parameter("machine_id") + @Parameter("address") + @Parameter("cabinet") + @Parameter("frame") + @GeneratesID + String INSERT_BMP_WITH_ID = """ + INSERT OR IGNORE INTO bmp( + bmp_id, machine_id, address, cabinet, frame) + VALUES (?, ?, ?, ?, ?) + """; + + /** Create a user, specifying the ID. */ + @Parameter("user_id") + @Parameter("user_name") + @Parameter("trust_level") + @Parameter("disabled") + @GeneratesID + String INSERT_USER = """ + INSERT OR IGNORE 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 OR IGNORE INTO 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 OR IGNORE INTO group_memberships( + membership_id, user_id, group_id) + VALUES (?, ?, ?) + """; + + /** Create a board, specifying the ID. */ + @Parameter("board_id") + @Parameter("address") + @Parameter("bmp_id") + @Parameter("board_num") + @Parameter("machine_id") + @Parameter("x") + @Parameter("y") + @Parameter("z") + @Parameter("root_x") + @Parameter("root_y") + @Parameter("board_power") + @GeneratesID + String INSERT_BOARD_WITH_ID = """ + INSERT OR IGNORE 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") + @Parameter("owner") + @Parameter("group_id") + @Parameter("root_id") + @Parameter("job_state") + @Parameter("create_timestamp") + @Parameter("allocation_timestamp") + @Parameter("death_timestamp") + @Parameter("allocation_size") + @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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """; +} 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 ede45bf158..90e92a5ff8 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 @@ -1,541 +1,541 @@ -/* - * Copyright (c) 2022 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 - * - * http://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; - -import static java.nio.file.Files.delete; -import static java.nio.file.Files.exists; -import static java.time.Duration.ofSeconds; -import static java.time.Instant.now; -import static java.time.Instant.ofEpochMilli; -import static java.time.Instant.ofEpochSecond; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.slf4j.LoggerFactory.getLogger; -import static uk.ac.manchester.spinnaker.alloc.db.Row.string; -import static uk.ac.manchester.spinnaker.alloc.model.JobState.DESTROYED; -import static uk.ac.manchester.spinnaker.alloc.model.JobState.QUEUED; -import static uk.ac.manchester.spinnaker.alloc.security.TrustLevel.BASIC; - -import java.io.IOException; -import java.nio.file.Paths; -import java.time.Duration; -import java.time.Instant; -import java.util.Collection; -import java.util.List; -import java.util.function.IntConsumer; -import java.util.function.ObjIntConsumer; - -import org.slf4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataAccessException; -import org.springframework.lang.NonNull; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; - -import uk.ac.manchester.spinnaker.alloc.db.DatabaseEngine; -import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connected; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Transacted; -import uk.ac.manchester.spinnaker.alloc.model.JobState; -import uk.ac.manchester.spinnaker.alloc.security.Permit; - -@SuppressWarnings({ - "checkstyle:ParameterNumber", "checkstyle:VisibilityModifier" -}) -public abstract class TestSupport extends SQLQueries implements SupportQueries { - /** Bring in the application Spring configuration that we're testing. */ - @Configuration - @ComponentScan(basePackageClasses = SpallocProperties.class) - public static class Config { - } - - protected static final Logger log = getLogger(TestSupport.class); - - /** Machine ID. */ - protected static final int MACHINE = 1000; - - /** Machine name. */ - protected static final String MACHINE_NAME = "foo_machine"; - - /** BMP ID. */ - protected static final int BMP = 2000; - - /** BMP IP address. */ - protected static final String BMP_ADDR = "1.1.1.1"; - - /** Board ID. */ - protected static final int BOARD = 3000; - - /** Board IP address. */ - protected static final String BOARD_ADDR = "2.2.2.2"; - - /** User ID. */ - protected static final int USER = 4000; - - /** User name. */ - public static final String USER_NAME = "user_bar"; - - /** Group ID. */ - protected static final int GROUP = 5000; - - /** Group name. */ - public static final String GROUP_NAME = "grill"; - - /** User-group membership ID. */ - protected static final int MEMBERSHIP = 6000; - - /** Initial quota. */ - protected static final long INITIAL_QUOTA = 1024; - - /** The DB. */ - @Autowired - protected DatabaseEngine db; - - /** The context connection to the DB. */ - protected Connection conn; - - /** - * Delete a DB file. It must not be open! - * - * @param dbPath - * Where the DB is. - * @throws IOException - * On failure. - */ - protected static void killDB(String dbPath) throws IOException { - var dbp = Paths.get(dbPath); - if (exists(dbp)) { - log.info("deleting old database: {}", dbp); - delete(dbp); - } - } - - 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); - } - try (var u = c.update(INSERT_BMP_WITH_ID)) { - u.call(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); - } - try (var u = c.update(INSERT_GROUP)) { - u.call(GROUP, GROUP_NAME, INITIAL_QUOTA); - } - try (var u = c.update(INSERT_MEMBER)) { - u.call(MEMBERSHIP, USER, GROUP); - } - } - - /** - * Set up a machine with one board, and a user. - */ - protected void setupDB1() { - try (var c = db.getConnection()) { - c.transaction(() -> setupDB1(c)); - } - } - - private static void setupDB1(Connection c) { - // A simple machine - makeMachine(c, 1, 1, 1); - // Add one board to the machine - try (var u = c.update(INSERT_BOARD_WITH_ID)) { - u.call(BOARD, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0, 0, 0, false); - } - // A disabled permission-less user with a quota - makeUser(c); - } - - /** - * Set up a machine with three boards, and a user. - */ - protected void setupDB3() { - try (var c = db.getConnection()) { - c.transaction(() -> setupDB3(c)); - } - } - - private static void setupDB3(Connection c) { - // A simple machine - makeMachine(c, 1, 1, 3); - // 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); - } - try (var u = c.update(INSERT_LINK)) { - u.call(b0, 0, b1, 3, true); - u.call(b0, 1, b2, 4, true); - u.call(b1, 2, b2, 5, true); - } - // A disabled permission-less user with a quota - makeUser(c); - } - - /** - * Insert a job of a given size and length. - * - * @param c - * DB connection - * @param root - * Root board, or {@code null} - * @param state - * Job state - * @param size - * Number of boards, or {@code null} - * @param createTime - * Time of creation, or {@code null} - * @param allocateTime - * Time of allocation, or {@code null} - * @param deathTime - * Time of death, or {@code null} - * @param keepalive - * Keepalive interval, or {@code null} - * @param keepaliveTime - * Time of last keepalive, or {@code null} - * @return Job ID - */ - protected static int makeJob(Connection c, Integer root, - @NonNull JobState state, Integer size, Instant createTime, - Instant allocateTime, Instant deathTime, Duration keepalive, - Instant keepaliveTime) { - try (var u = c.update(INSERT_JOB_WITH_TIMESTAMPS)) { - return u.key(MACHINE, USER, GROUP, root, state, createTime, - allocateTime, deathTime, size, keepalive, keepaliveTime) - .orElseThrow( - () -> new RuntimeException("failed to insert job")); - } - } - - /** - * Insert a dead job of a given size and length. - * - * @param c - * DB connection - * @param size - * Number of boards - * @param time - * Length of time (seconds) - * @return Job ID - */ - protected static int makeFinishedJob(Connection c, int size, int time) { - return makeJob(c, BOARD, DESTROYED, size, ofEpochSecond(0), - ofEpochSecond(time), ofEpochSecond(time + time), - ofSeconds(time), null); - } - - /** - * Directly manipulate the allocation. - * - * @param c - * DB connection - * @param boardId - * What board are we changing - * @param jobId - * What job are we assigning - */ - 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 - """)) { - u.call(jobId, boardId); - } - } - - /** - * Directly manipulate the reverse of the allocation (root only). - * - * @param c - * DB connection - * @param jobId - * What job are we changing - * @param boardId - * What board are we assigning as the root - */ - 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 - """)) { - u.call(boardId, jobId); - } - } - - protected List getReports() { - return db.execute(c -> { - try (var q = c.query(""" - SELECT reported_issue - FROM board_reports - """)) { - return q.call().map(string("reported_issue")).toList(); - } - }); - } - - protected void killReports() { - db.executeVoid(c -> { - try (var u = c.update("DELETE from board_reports")) { - u.call(); - } - }); - } - - protected void checkAndRollback(Connected act) { - db.executeVoid(c -> { - try { - conn = c; - act.act(c); - } finally { - c.rollback(); - } - }); - } - - protected void doTransactionalTest(Transacted action) { - try (var c = db.getConnection()) { - c.transaction(() -> { - try { - conn = c; - action.act(); - } finally { - try { - c.rollback(); - } catch (DataAccessException ignored) { - log.trace("ignoring DAE from rollback", ignored); - } - conn = null; - } - }); - } - } - - /** - * Insert a live job. Needs a matching allocation request. - * - * @param time - * Length of time for keepalive (seconds) - * @return Job ID - */ - protected int makeQueuedJob(int time) { - return makeJob(conn, null, QUEUED, null, ofEpochMilli(0), null, null, - ofSeconds(time), now()); - } - - protected void makeAllocBySizeRequest(int job, int size) { - try (var u = conn.update(TEST_INSERT_REQ_SIZE)) { - conn.transaction(() -> u.call(job, size)); - } - } - - protected void makeAllocByDimensionsRequest(int job, int width, int height, - int allowedDead) { - try (var u = conn.update(TEST_INSERT_REQ_DIMS)) { - conn.transaction(() -> u.call(job, width, height, allowedDead)); - } - } - - protected void makeAllocByBoardIdRequest(int job, int board) { - try (var u = conn.update(TEST_INSERT_REQ_BOARD)) { - conn.transaction(() -> u.call(job, board)); - } - } - - protected JobState getJobState(int job) { - try (var q = conn.query(GET_JOB)) { - return conn.transaction(() -> q.call1(job).orElseThrow() - .getEnum("job_state", JobState.class)); - } - } - - protected int getJobRequestCount() { - try (var q = conn.query(TEST_COUNT_REQUESTS)) { - return conn.transaction( - () -> q.call1(QUEUED).orElseThrow().getInt("cnt")); - } - } - - protected int getPendingPowerChanges() { - try (var q = conn.query(TEST_COUNT_POWER_CHANGES)) { - return conn - .transaction(() -> q.call1().orElseThrow().getInt("cnt")); - } - } - - // Wrappers for temporarily putting the DB into a state with a job/alloc - - protected int makeJob() { - return db.execute(c -> makeJob(c, null, QUEUED, null, - ofEpochMilli(0), null, null, ofSeconds(0), now())); - } - - protected void withJob(IntConsumer act) { - int jobId = makeJob(); - try { - act.accept(jobId); - } finally { - nukeJob(jobId); - } - } - - protected void nukeJob(int jobId) { - db.executeVoid(c -> { - try (var u = c.update(""" - DELETE FROM jobs - WHERE job_id = ? - """)) { - u.call(jobId); - } - }); - } - - protected void withAllocation(int jobId, Runnable act) { - db.executeVoid(c -> { - allocateBoardToJob(c, BOARD, jobId); - setAllocRoot(c, jobId, BOARD); - }); - try { - act.run(); - } finally { - db.executeVoid(c -> { - allocateBoardToJob(c, BOARD, null); - setAllocRoot(c, jobId, null); - }); - } - } - - protected void withStandardAllocatedJob(ObjIntConsumer act) { - // Composite op, for brevity - withJob(jobId -> inContext(c -> withAllocation(jobId, - () -> act.accept(c.setAuth(USER_NAME), jobId)))); - } - - private static final int DELAY_MS = 1000; - - /** Sleep for one second. */ - protected static void snooze1s() { - try { - Thread.sleep(DELAY_MS); - } catch (InterruptedException e) { - assumeTrue(false, "sleep() was interrupted"); - } - } - - /** Capability provided by {@link #inContext(InC)} to what it guards. */ - public interface C { - /** - * Install an authentication token. - * - * @param auth - * The authentication token to install. {@code null} to - * remove. - */ - void setAuth(Authentication auth); - - /** - * Install the named user as the current user and provide a permit that - * allows that user to touch resources. - * - * @param name - * The user name. - * @return The newly-minted permit. - */ - default Permit setAuth(String name) { - @SuppressWarnings("serial") - var a = new Authentication() { - @Override - public String getName() { - return name; - } - - @Override - public Collection getAuthorities() { - return List.of(); - } - - @Override - public Object getCredentials() { - return null; - } - - @Override - public Object getDetails() { - return null; - } - - @Override - public Object getPrincipal() { - return null; - } - - @Override - public boolean isAuthenticated() { - return true; - } - - @Override - public void setAuthenticated(boolean isAuthenticated) { - } - }; - setAuth(a); - return new Permit(SecurityContextHolder.getContext()); - } - } - - /** - * An action wrapped by {@link #inContext(InC)}. - */ - public interface InC { - /** - * The wrapped action. - * - * @param c - * The capability to set the current user. - */ - void act(C c); - } - - /** - * Run code with the capability to set the current user. Will clean up - * afterwards. - * - * @param inc - * The code to run. - */ - public static void inContext(InC inc) { - var context = SecurityContextHolder.getContext(); - try { - inc.act(context::setAuthentication); - } finally { - context.setAuthentication(null); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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; + +import static java.nio.file.Files.delete; +import static java.nio.file.Files.exists; +import static java.time.Duration.ofSeconds; +import static java.time.Instant.now; +import static java.time.Instant.ofEpochMilli; +import static java.time.Instant.ofEpochSecond; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.slf4j.LoggerFactory.getLogger; +import static uk.ac.manchester.spinnaker.alloc.db.Row.string; +import static uk.ac.manchester.spinnaker.alloc.model.JobState.DESTROYED; +import static uk.ac.manchester.spinnaker.alloc.model.JobState.QUEUED; +import static uk.ac.manchester.spinnaker.alloc.security.TrustLevel.BASIC; + +import java.io.IOException; +import java.nio.file.Paths; +import java.time.Duration; +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.function.IntConsumer; +import java.util.function.ObjIntConsumer; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.DataAccessException; +import org.springframework.lang.NonNull; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; + +import uk.ac.manchester.spinnaker.alloc.db.DatabaseEngine; +import uk.ac.manchester.spinnaker.alloc.db.SQLQueries; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connected; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Transacted; +import uk.ac.manchester.spinnaker.alloc.model.JobState; +import uk.ac.manchester.spinnaker.alloc.security.Permit; + +@SuppressWarnings({ + "checkstyle:ParameterNumber", "checkstyle:VisibilityModifier" +}) +public abstract class TestSupport extends SQLQueries implements SupportQueries { + /** Bring in the application Spring configuration that we're testing. */ + @Configuration + @ComponentScan(basePackageClasses = SpallocProperties.class) + public static class Config { + } + + protected static final Logger log = getLogger(TestSupport.class); + + /** Machine ID. */ + protected static final int MACHINE = 1000; + + /** Machine name. */ + protected static final String MACHINE_NAME = "foo_machine"; + + /** BMP ID. */ + protected static final int BMP = 2000; + + /** BMP IP address. */ + protected static final String BMP_ADDR = "1.1.1.1"; + + /** Board ID. */ + protected static final int BOARD = 3000; + + /** Board IP address. */ + protected static final String BOARD_ADDR = "2.2.2.2"; + + /** User ID. */ + protected static final int USER = 4000; + + /** User name. */ + public static final String USER_NAME = "user_bar"; + + /** Group ID. */ + protected static final int GROUP = 5000; + + /** Group name. */ + public static final String GROUP_NAME = "grill"; + + /** User-group membership ID. */ + protected static final int MEMBERSHIP = 6000; + + /** Initial quota. */ + protected static final long INITIAL_QUOTA = 1024; + + /** The DB. */ + @Autowired + protected DatabaseEngine db; + + /** The context connection to the DB. */ + protected Connection conn; + + /** + * Delete a DB file. It must not be open! + * + * @param dbPath + * Where the DB is. + * @throws IOException + * On failure. + */ + protected static void killDB(String dbPath) throws IOException { + var dbp = Paths.get(dbPath); + if (exists(dbp)) { + log.info("deleting old database: {}", dbp); + delete(dbp); + } + } + + 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); + } + try (var u = c.update(INSERT_BMP_WITH_ID)) { + u.call(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); + } + try (var u = c.update(INSERT_GROUP)) { + u.call(GROUP, GROUP_NAME, INITIAL_QUOTA); + } + try (var u = c.update(INSERT_MEMBER)) { + u.call(MEMBERSHIP, USER, GROUP); + } + } + + /** + * Set up a machine with one board, and a user. + */ + protected void setupDB1() { + try (var c = db.getConnection()) { + c.transaction(() -> setupDB1(c)); + } + } + + private static void setupDB1(Connection c) { + // A simple machine + makeMachine(c, 1, 1, 1); + // Add one board to the machine + try (var u = c.update(INSERT_BOARD_WITH_ID)) { + u.call(BOARD, BOARD_ADDR, BMP, 0, MACHINE, 0, 0, 0, 0, 0, false); + } + // A disabled permission-less user with a quota + makeUser(c); + } + + /** + * Set up a machine with three boards, and a user. + */ + protected void setupDB3() { + try (var c = db.getConnection()) { + c.transaction(() -> setupDB3(c)); + } + } + + private static void setupDB3(Connection c) { + // A simple machine + makeMachine(c, 1, 1, 3); + // 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); + } + try (var u = c.update(INSERT_LINK)) { + u.call(b0, 0, b1, 3, true); + u.call(b0, 1, b2, 4, true); + u.call(b1, 2, b2, 5, true); + } + // A disabled permission-less user with a quota + makeUser(c); + } + + /** + * Insert a job of a given size and length. + * + * @param c + * DB connection + * @param root + * Root board, or {@code null} + * @param state + * Job state + * @param size + * Number of boards, or {@code null} + * @param createTime + * Time of creation, or {@code null} + * @param allocateTime + * Time of allocation, or {@code null} + * @param deathTime + * Time of death, or {@code null} + * @param keepalive + * Keepalive interval, or {@code null} + * @param keepaliveTime + * Time of last keepalive, or {@code null} + * @return Job ID + */ + protected static int makeJob(Connection c, Integer root, + @NonNull JobState state, Integer size, Instant createTime, + Instant allocateTime, Instant deathTime, Duration keepalive, + Instant keepaliveTime) { + try (var u = c.update(INSERT_JOB_WITH_TIMESTAMPS)) { + return u.key(MACHINE, USER, GROUP, root, state, createTime, + allocateTime, deathTime, size, keepalive, keepaliveTime) + .orElseThrow( + () -> new RuntimeException("failed to insert job")); + } + } + + /** + * Insert a dead job of a given size and length. + * + * @param c + * DB connection + * @param size + * Number of boards + * @param time + * Length of time (seconds) + * @return Job ID + */ + protected static int makeFinishedJob(Connection c, int size, int time) { + return makeJob(c, BOARD, DESTROYED, size, ofEpochSecond(0), + ofEpochSecond(time), ofEpochSecond(time + time), + ofSeconds(time), null); + } + + /** + * Directly manipulate the allocation. + * + * @param c + * DB connection + * @param boardId + * What board are we changing + * @param jobId + * What job are we assigning + */ + 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 + """)) { + u.call(jobId, boardId); + } + } + + /** + * Directly manipulate the reverse of the allocation (root only). + * + * @param c + * DB connection + * @param jobId + * What job are we changing + * @param boardId + * What board are we assigning as the root + */ + 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 + """)) { + u.call(boardId, jobId); + } + } + + protected List getReports() { + return db.execute(c -> { + try (var q = c.query(""" + SELECT reported_issue + FROM board_reports + """)) { + return q.call().map(string("reported_issue")).toList(); + } + }); + } + + protected void killReports() { + db.executeVoid(c -> { + try (var u = c.update("DELETE from board_reports")) { + u.call(); + } + }); + } + + protected void checkAndRollback(Connected act) { + db.executeVoid(c -> { + try { + conn = c; + act.act(c); + } finally { + c.rollback(); + } + }); + } + + protected void doTransactionalTest(Transacted action) { + try (var c = db.getConnection()) { + c.transaction(() -> { + try { + conn = c; + action.act(); + } finally { + try { + c.rollback(); + } catch (DataAccessException ignored) { + log.trace("ignoring DAE from rollback", ignored); + } + conn = null; + } + }); + } + } + + /** + * Insert a live job. Needs a matching allocation request. + * + * @param time + * Length of time for keepalive (seconds) + * @return Job ID + */ + protected int makeQueuedJob(int time) { + return makeJob(conn, null, QUEUED, null, ofEpochMilli(0), null, null, + ofSeconds(time), now()); + } + + protected void makeAllocBySizeRequest(int job, int size) { + try (var u = conn.update(TEST_INSERT_REQ_SIZE)) { + conn.transaction(() -> u.call(job, size)); + } + } + + protected void makeAllocByDimensionsRequest(int job, int width, int height, + int allowedDead) { + try (var u = conn.update(TEST_INSERT_REQ_DIMS)) { + conn.transaction(() -> u.call(job, width, height, allowedDead)); + } + } + + protected void makeAllocByBoardIdRequest(int job, int board) { + try (var u = conn.update(TEST_INSERT_REQ_BOARD)) { + conn.transaction(() -> u.call(job, board)); + } + } + + protected JobState getJobState(int job) { + try (var q = conn.query(GET_JOB)) { + return conn.transaction(() -> q.call1(job).orElseThrow() + .getEnum("job_state", JobState.class)); + } + } + + protected int getJobRequestCount() { + try (var q = conn.query(TEST_COUNT_REQUESTS)) { + return conn.transaction( + () -> q.call1(QUEUED).orElseThrow().getInt("cnt")); + } + } + + protected int getPendingPowerChanges() { + try (var q = conn.query(TEST_COUNT_POWER_CHANGES)) { + return conn + .transaction(() -> q.call1().orElseThrow().getInt("cnt")); + } + } + + // Wrappers for temporarily putting the DB into a state with a job/alloc + + protected int makeJob() { + return db.execute(c -> makeJob(c, null, QUEUED, null, + ofEpochMilli(0), null, null, ofSeconds(0), now())); + } + + protected void withJob(IntConsumer act) { + int jobId = makeJob(); + try { + act.accept(jobId); + } finally { + nukeJob(jobId); + } + } + + protected void nukeJob(int jobId) { + db.executeVoid(c -> { + try (var u = c.update(""" + DELETE FROM jobs + WHERE job_id = ? + """)) { + u.call(jobId); + } + }); + } + + protected void withAllocation(int jobId, Runnable act) { + db.executeVoid(c -> { + allocateBoardToJob(c, BOARD, jobId); + setAllocRoot(c, jobId, BOARD); + }); + try { + act.run(); + } finally { + db.executeVoid(c -> { + allocateBoardToJob(c, BOARD, null); + setAllocRoot(c, jobId, null); + }); + } + } + + protected void withStandardAllocatedJob(ObjIntConsumer act) { + // Composite op, for brevity + withJob(jobId -> inContext(c -> withAllocation(jobId, + () -> act.accept(c.setAuth(USER_NAME), jobId)))); + } + + private static final int DELAY_MS = 1000; + + /** Sleep for one second. */ + protected static void snooze1s() { + try { + Thread.sleep(DELAY_MS); + } catch (InterruptedException e) { + assumeTrue(false, "sleep() was interrupted"); + } + } + + /** Capability provided by {@link #inContext(InC)} to what it guards. */ + public interface C { + /** + * Install an authentication token. + * + * @param auth + * The authentication token to install. {@code null} to + * remove. + */ + void setAuth(Authentication auth); + + /** + * Install the named user as the current user and provide a permit that + * allows that user to touch resources. + * + * @param name + * The user name. + * @return The newly-minted permit. + */ + default Permit setAuth(String name) { + @SuppressWarnings("serial") + var a = new Authentication() { + @Override + public String getName() { + return name; + } + + @Override + public Collection getAuthorities() { + return List.of(); + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public Object getPrincipal() { + return null; + } + + @Override + public boolean isAuthenticated() { + return true; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) { + } + }; + setAuth(a); + return new Permit(SecurityContextHolder.getContext()); + } + } + + /** + * An action wrapped by {@link #inContext(InC)}. + */ + public interface InC { + /** + * The wrapped action. + * + * @param c + * The capability to set the current user. + */ + void act(C c); + } + + /** + * Run code with the capability to set the current user. Will clean up + * afterwards. + * + * @param inc + * The code to run. + */ + public static void inContext(InC inc) { + var context = SecurityContextHolder.getContext(); + try { + inc.act(context::setAuthentication); + } finally { + context.setAuthentication(null); + } + } +} 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 ec29d957b3..f854a0b1d6 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 @@ -1,291 +1,291 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.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; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.HashMap; -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 uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.machine.board.BMPBoard; -import uk.ac.manchester.spinnaker.machine.board.BMPCoords; -import uk.ac.manchester.spinnaker.messages.model.BMPConnectionData; -import uk.ac.manchester.spinnaker.messages.model.Blacklist; -import uk.ac.manchester.spinnaker.messages.model.FPGA; -import uk.ac.manchester.spinnaker.messages.model.PowerCommand; -import uk.ac.manchester.spinnaker.messages.model.VersionInfo; -import uk.ac.manchester.spinnaker.transceiver.UnimplementedBMPTransceiver; -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * BMP transceiver mock just for test purposes. - */ -public final class MockTransceiver extends UnimplementedBMPTransceiver { - private static final Logger log = getLogger(MockTransceiver.class); - - /** - * Install this mock transceiver as the thing to be manufactured by the - * given transceiver factory. - * - * @param txrxFactory - * The transceiver factory to install into. - */ - @SuppressWarnings("deprecation") - public static void installIntoFactory(TransceiverFactory txrxFactory) { - txrxFactory.getTestAPI().setFactory(MockTransceiver::new); - } - - private static MockTransceiver current; - - public static MockTransceiver getCurrentMock() { - return current; - } - - /** Not a real serial number at all! Just for testing purposes. */ - private static final String SERIAL_NUMBER = "gorp"; - - private static final int VERSION_INFO_SIZE = 32; - - /** Dummy version code. */ - static final short VERSION = 0x202; - - /** Initial dummy blacklist data. */ - static final String BLACKLIST = "chip 5 5 core 5"; - - private static String blacklistData = BLACKLIST; - - private static VersionInfo version = - new VersionInfo(syntheticVersionData(VERSION), true); - - private Map status; - - @GuardedBy("itself") - private final ValueHolder setBlacklist; - - private MockTransceiver(String machineName, BMPConnectionData data, - ValueHolder setBlacklist) { - log.info("constructed dummy transceiver for {} ({} : {})", machineName, - data.ipAddress(), data.boards()); - status = new HashMap<>(); - this.setBlacklist = setBlacklist; - current = this; - } - - public static void setVersion(short versionCode) { - version = new VersionInfo(syntheticVersionData(versionCode), true); - } - - public static void setBlacklist(String blacklist) { - blacklistData = blacklist; - } - - /** - * @return The bytes of a response, correct in the places which Spalloc - * checks, and arbitrary (zero) elsewhere. - */ - private static ByteBuffer syntheticVersionData(short versionCode) { - byte zero = 0; - var b = allocate(VERSION_INFO_SIZE).order(LITTLE_ENDIAN); - b.put(zero); - b.put(zero); - b.put(zero); - b.put(zero); - b.putShort((short) 0); - b.putShort(versionCode); - b.putInt(0); - b.put("abc/def".getBytes(UTF_8)); - return b.flip(); - } - - public Map getStatus() { - return unmodifiableMap(status); - } - - @Override - 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); - } - } - - /** - * A place where you can set a queue of wonky results from the read of the - * FPGA registers. - */ - @SuppressWarnings("checkstyle:visibilitymodifier") - public static ArrayDeque fpgaResults = new ArrayDeque<>(); - - @Override - public int readFPGARegister(FPGA fpga, MemoryLocation register, - BMPCoords bmp, BMPBoard board) { - log.info("readFPGARegister({},{},{},{})", fpga, register, bmp, board); - var r = fpgaResults.pollFirst(); - if (r != null) { - return r.value; - } - return fpga.value; - } - - @Override - public void writeFPGARegister(FPGA fpga, MemoryLocation register, int value, - BMPCoords bmp, BMPBoard board) { - log.info("writeFPGARegister({},{},{},{},{})", fpga, register, value, - bmp, board); - } - - @Override - public VersionInfo readBMPVersion(BMPCoords bmp, BMPBoard board) { - log.info("readBMPVersion({},{})", bmp, board); - return version; - } - - @Override - public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) { - log.info("readBoardSerialNumber({},{})", bmp, board); - return SERIAL_NUMBER; - } - - private static final int MEM_SIZE = 8 * 1024 * 1024; - - private static ByteBuffer allocateMemory() { - var buf = allocate(MEM_SIZE).order(LITTLE_ENDIAN); - buf.position(0).limit(MEM_SIZE); - return buf; - } - - private ByteBuffer memory = allocateMemory(); - - private ByteBuffer flash = allocateMemory(); - - @Override - public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, - length); - // Pad to length - 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); - } - return b; - } - - @Override - public ByteBuffer readBMPMemory(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readBMPMemory({},{},{},{})", bmp, board, baseAddress, length); - return memory.slice(baseAddress.address(), length).order(LITTLE_ENDIAN); - } - - @Override - public MemoryLocation getSerialFlashBuffer(BMPCoords bmp, BMPBoard board) { - log.info("getSerialFlashBuffer({},{})", bmp, board); - return MemoryLocation.NULL; - } - - @Override - public void writeBMPMemory(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, ByteBuffer data) { - log.info("writeBMPMemory({},{},{}:{})", bmp, board, baseAddress, - data.remaining()); - memory.slice(baseAddress.address(), data.remaining()) - .put(data.duplicate()); - } - - @Override - public void writeFlash(@Valid BMPCoords bmp, @Valid BMPBoard board, - @NotNull MemoryLocation baseAddress, @NotNull ByteBuffer data, - boolean update) { - log.info("writeFlash({},{},{},{})", bmp, board, baseAddress, - data.remaining()); - var blData = data.duplicate().position(BMP_FLASH_BLACKLIST_OFFSET); - synchronized (setBlacklist) { - setBlacklist.setValue(new Blacklist(blData)); - } - } - - private static final int BMP_FLASH_BLACKLIST_OFFSET = 0xe00; - - private static final int SERIAL_FLASH_BLACKLIST_OFFSET = 0x100; - - @Override - public void writeSerialFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, ByteBuffer data) { - log.info("writeSerialFlash({},{},{}:{})", bmp, board, baseAddress, - data.remaining()); - 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) { - if (!bl.equals(setBlacklist.getValue())) { - throw new IllegalStateException("blacklist in serial flash (" - + bl + ") is different to blacklist in BMP flash (" - + setBlacklist.getValue() + ")"); - } - } - } - - @Override - public void writeSerialFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int size, InputStream stream) - throws IOException { - log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress, - size); - flash.slice(baseAddress.address(), size).put(readFully(stream, size)); - } - - @Override - public void writeBMPFlash(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress) { - log.info("writeBMPFlash({},{},{})", bmp, board, baseAddress); - } - - private static final long CRC_MASK = 0xffffffffL; - - @Override - public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board, - MemoryLocation baseAddress, int length) { - log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress, - length); - var crc = new CRC32(); - crc.update(flash.slice(baseAddress.address(), length)); - return (int) (crc.getValue() & CRC_MASK); - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.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; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.HashMap; +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 uk.ac.manchester.spinnaker.machine.MemoryLocation; +import uk.ac.manchester.spinnaker.machine.board.BMPBoard; +import uk.ac.manchester.spinnaker.machine.board.BMPCoords; +import uk.ac.manchester.spinnaker.messages.model.BMPConnectionData; +import uk.ac.manchester.spinnaker.messages.model.Blacklist; +import uk.ac.manchester.spinnaker.messages.model.FPGA; +import uk.ac.manchester.spinnaker.messages.model.PowerCommand; +import uk.ac.manchester.spinnaker.messages.model.VersionInfo; +import uk.ac.manchester.spinnaker.transceiver.UnimplementedBMPTransceiver; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * BMP transceiver mock just for test purposes. + */ +public final class MockTransceiver extends UnimplementedBMPTransceiver { + private static final Logger log = getLogger(MockTransceiver.class); + + /** + * Install this mock transceiver as the thing to be manufactured by the + * given transceiver factory. + * + * @param txrxFactory + * The transceiver factory to install into. + */ + @SuppressWarnings("deprecation") + public static void installIntoFactory(TransceiverFactory txrxFactory) { + txrxFactory.getTestAPI().setFactory(MockTransceiver::new); + } + + private static MockTransceiver current; + + public static MockTransceiver getCurrentMock() { + return current; + } + + /** Not a real serial number at all! Just for testing purposes. */ + private static final String SERIAL_NUMBER = "gorp"; + + private static final int VERSION_INFO_SIZE = 32; + + /** Dummy version code. */ + static final short VERSION = 0x202; + + /** Initial dummy blacklist data. */ + static final String BLACKLIST = "chip 5 5 core 5"; + + private static String blacklistData = BLACKLIST; + + private static VersionInfo version = + new VersionInfo(syntheticVersionData(VERSION), true); + + private Map status; + + @GuardedBy("itself") + private final ValueHolder setBlacklist; + + private MockTransceiver(String machineName, BMPConnectionData data, + ValueHolder setBlacklist) { + log.info("constructed dummy transceiver for {} ({} : {})", machineName, + data.ipAddress(), data.boards()); + status = new HashMap<>(); + this.setBlacklist = setBlacklist; + current = this; + } + + public static void setVersion(short versionCode) { + version = new VersionInfo(syntheticVersionData(versionCode), true); + } + + public static void setBlacklist(String blacklist) { + blacklistData = blacklist; + } + + /** + * @return The bytes of a response, correct in the places which Spalloc + * checks, and arbitrary (zero) elsewhere. + */ + private static ByteBuffer syntheticVersionData(short versionCode) { + byte zero = 0; + var b = allocate(VERSION_INFO_SIZE).order(LITTLE_ENDIAN); + b.put(zero); + b.put(zero); + b.put(zero); + b.put(zero); + b.putShort((short) 0); + b.putShort(versionCode); + b.putInt(0); + b.put("abc/def".getBytes(UTF_8)); + return b.flip(); + } + + public Map getStatus() { + return unmodifiableMap(status); + } + + @Override + 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); + } + } + + /** + * A place where you can set a queue of wonky results from the read of the + * FPGA registers. + */ + @SuppressWarnings("checkstyle:visibilitymodifier") + public static ArrayDeque fpgaResults = new ArrayDeque<>(); + + @Override + public int readFPGARegister(FPGA fpga, MemoryLocation register, + BMPCoords bmp, BMPBoard board) { + log.info("readFPGARegister({},{},{},{})", fpga, register, bmp, board); + var r = fpgaResults.pollFirst(); + if (r != null) { + return r.value; + } + return fpga.value; + } + + @Override + public void writeFPGARegister(FPGA fpga, MemoryLocation register, int value, + BMPCoords bmp, BMPBoard board) { + log.info("writeFPGARegister({},{},{},{},{})", fpga, register, value, + bmp, board); + } + + @Override + public VersionInfo readBMPVersion(BMPCoords bmp, BMPBoard board) { + log.info("readBMPVersion({},{})", bmp, board); + return version; + } + + @Override + public String readBoardSerialNumber(BMPCoords bmp, BMPBoard board) { + log.info("readBoardSerialNumber({},{})", bmp, board); + return SERIAL_NUMBER; + } + + private static final int MEM_SIZE = 8 * 1024 * 1024; + + private static ByteBuffer allocateMemory() { + var buf = allocate(MEM_SIZE).order(LITTLE_ENDIAN); + buf.position(0).limit(MEM_SIZE); + return buf; + } + + private ByteBuffer memory = allocateMemory(); + + private ByteBuffer flash = allocateMemory(); + + @Override + public ByteBuffer readSerialFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readSerialFlash({},{},{},{})", bmp, board, baseAddress, + length); + // Pad to length + 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); + } + return b; + } + + @Override + public ByteBuffer readBMPMemory(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readBMPMemory({},{},{},{})", bmp, board, baseAddress, length); + return memory.slice(baseAddress.address(), length).order(LITTLE_ENDIAN); + } + + @Override + public MemoryLocation getSerialFlashBuffer(BMPCoords bmp, BMPBoard board) { + log.info("getSerialFlashBuffer({},{})", bmp, board); + return MemoryLocation.NULL; + } + + @Override + public void writeBMPMemory(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, ByteBuffer data) { + log.info("writeBMPMemory({},{},{}:{})", bmp, board, baseAddress, + data.remaining()); + memory.slice(baseAddress.address(), data.remaining()) + .put(data.duplicate()); + } + + @Override + public void writeFlash(@Valid BMPCoords bmp, @Valid BMPBoard board, + @NotNull MemoryLocation baseAddress, @NotNull ByteBuffer data, + boolean update) { + log.info("writeFlash({},{},{},{})", bmp, board, baseAddress, + data.remaining()); + var blData = data.duplicate().position(BMP_FLASH_BLACKLIST_OFFSET); + synchronized (setBlacklist) { + setBlacklist.setValue(new Blacklist(blData)); + } + } + + private static final int BMP_FLASH_BLACKLIST_OFFSET = 0xe00; + + private static final int SERIAL_FLASH_BLACKLIST_OFFSET = 0x100; + + @Override + public void writeSerialFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, ByteBuffer data) { + log.info("writeSerialFlash({},{},{}:{})", bmp, board, baseAddress, + data.remaining()); + 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) { + if (!bl.equals(setBlacklist.getValue())) { + throw new IllegalStateException("blacklist in serial flash (" + + bl + ") is different to blacklist in BMP flash (" + + setBlacklist.getValue() + ")"); + } + } + } + + @Override + public void writeSerialFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int size, InputStream stream) + throws IOException { + log.info("writeSerialFlash({},{},{},{})", bmp, board, baseAddress, + size); + flash.slice(baseAddress.address(), size).put(readFully(stream, size)); + } + + @Override + public void writeBMPFlash(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress) { + log.info("writeBMPFlash({},{},{})", bmp, board, baseAddress); + } + + private static final long CRC_MASK = 0xffffffffL; + + @Override + public int readSerialFlashCRC(BMPCoords bmp, BMPBoard board, + MemoryLocation baseAddress, int length) { + log.info("readSerialFlashCRC({},{},{},{})", bmp, board, baseAddress, + length); + var crc = new CRC32(); + 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/db/MemDBTestBase.java b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java index e4ac719e08..12d88413c3 100644 --- a/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java +++ b/SpiNNaker-allocserv/src/test/java/uk/ac/manchester/spinnaker/alloc/db/MemDBTestBase.java @@ -1,65 +1,65 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.db; - -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * Support class for doing testing against an in-memory database. There will be - * a connection per test (i.e., the DB will be implicitly deleted at the end of - * each test), with that connection made available in the {@link #c} - * field. That field must not be modified by subclasses. - *

- * Subclasses should be annotated with {@link SpringBootTest}. - */ -@UsedInJavadocOnly(SpringBootTest.class) -public abstract class MemDBTestBase extends SQLQueries { - private DatabaseEngine memdb; - - /** - * The DB connection. Only valid in a test. Must not be modified by - * subclasses. - */ - @SuppressWarnings("checkstyle:visibilitymodifier") - protected Connection c; - - @BeforeAll - void getMemoryDatabase(@Autowired DatabaseEngine mainDBEngine) { - assumeTrue(mainDBEngine != null, "spring-configured DB engine absent"); - memdb = mainDBEngine.getInMemoryDB(); - } - - @BeforeEach - @SuppressWarnings("MustBeClosed") - void getConnection() { - c = memdb.getConnection(); - assumeTrue(c != null, "connection not generated"); - } - - @AfterEach - void closeConnection() { - c.close(); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.db; + +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import uk.ac.manchester.spinnaker.alloc.db.DatabaseAPI.Connection; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * Support class for doing testing against an in-memory database. There will be + * a connection per test (i.e., the DB will be implicitly deleted at the end of + * each test), with that connection made available in the {@link #c} + * field. That field must not be modified by subclasses. + *

+ * Subclasses should be annotated with {@link SpringBootTest}. + */ +@UsedInJavadocOnly(SpringBootTest.class) +public abstract class MemDBTestBase extends SQLQueries { + private DatabaseEngine memdb; + + /** + * The DB connection. Only valid in a test. Must not be modified by + * subclasses. + */ + @SuppressWarnings("checkstyle:visibilitymodifier") + protected Connection c; + + @BeforeAll + void getMemoryDatabase(@Autowired DatabaseEngine mainDBEngine) { + assumeTrue(mainDBEngine != null, "spring-configured DB engine absent"); + memdb = mainDBEngine.getInMemoryDB(); + } + + @BeforeEach + @SuppressWarnings("MustBeClosed") + void getConnection() { + c = memdb.getConnection(); + assumeTrue(c != null, "connection not generated"); + } + + @AfterEach + void closeConnection() { + c.close(); + } +} diff --git a/SpiNNaker-allocserv/src/test/resources/three-board-example.json b/SpiNNaker-allocserv/src/test/resources/three-board-example.json index d051efbc05..22d901c45b 100644 --- a/SpiNNaker-allocserv/src/test/resources/three-board-example.json +++ b/SpiNNaker-allocserv/src/test/resources/three-board-example.json @@ -1 +1 @@ -{"machines":[{"name":"SpiNNaker3board","tags":["machine-room","default"],"width":1,"height":1,"dead-boards":[],"dead-links":{},"board-locations":{"[x:0,y:0,z:0]":{"c":0,"f":0,"b":0},"[x:0,y:0,z:1]":{"c":0,"f":0,"b":2},"[x:0,y:0,z:2]":{"c":0,"f":0,"b":1}},"bmp-ips":{"[c:0,f:0]":"10.11.193.0"},"spinnaker-ips":{"[x:0,y:0,z:0]":"10.11.193.1","[x:0,y:0,z:1]":"10.11.193.17","[x:0,y:0,z:2]":"10.11.193.9"}}],"port":22244,"ip":"127.0.0.1","timeout-check-interval":5.0,"max-retired-jobs":1200,"seconds-before-free":30} \ No newline at end of file +{"machines":[{"name":"SpiNNaker3board","tags":["machine-room","default"],"width":1,"height":1,"dead-boards":[],"dead-links":{},"board-locations":{"[x:0,y:0,z:0]":{"c":0,"f":0,"b":0},"[x:0,y:0,z:1]":{"c":0,"f":0,"b":2},"[x:0,y:0,z:2]":{"c":0,"f":0,"b":1}},"bmp-ips":{"[c:0,f:0]":"10.11.193.0"},"spinnaker-ips":{"[x:0,y:0,z:0]":"10.11.193.1","[x:0,y:0,z:1]":"10.11.193.17","[x:0,y:0,z:2]":"10.11.193.9"}}],"port":22244,"ip":"127.0.0.1","timeout-check-interval":5.0,"max-retired-jobs":1200,"seconds-before-free":30} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java index 9a43ea2840..b24f518c2e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ClientUtils.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.net.SocketTimeoutException; -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.BlockingQueue; - -/** Shared helper because we can't use a superclass. */ -abstract class ClientUtils { - private ClientUtils() { - } - - /** - * Receive a message from a queue or time out. - * - * @param received - * Where to receive from. - * @param timeout - * Timeout, in milliseconds. - * @return The message. - * @throws InterruptedException - * If communications are interrupted. - * @throws SocketTimeoutException - * If a timeout happens. - */ - static ByteBuffer receiveHelper(BlockingQueue received, - long timeout) throws SocketTimeoutException, InterruptedException { - var msg = received.poll(timeout, MILLISECONDS); - if (isNull(msg)) { - throw new SocketTimeoutException(); - } - return msg; - } - - /** - * Add a {@code /} to the end of the path part of a URI. - * - * @param uri - * The URI to amend. Assumed to be HTTP or HTTPS. - * @return The amended URI. - */ - static URI asDir(URI uri) { - var path = uri.getPath(); - if (!path.endsWith("/")) { - path += "/"; - uri = uri.resolve(path); - } - return uri; - } - - /** - * Make a read-only shallow copy of a list. - * - * @param - * The type of elements in the list. These are - * recommended to be immutable, but this is not - * enforced. - * @param list - * The list to make a read-only copy of. The elements in the list - * are not themselves copied. - * @return The read-only copy. - */ - static List readOnlyCopy(List list) { - return Objects.isNull(list) ? List.of() : List.copyOf(list); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.net.SocketTimeoutException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.BlockingQueue; + +/** Shared helper because we can't use a superclass. */ +abstract class ClientUtils { + private ClientUtils() { + } + + /** + * Receive a message from a queue or time out. + * + * @param received + * Where to receive from. + * @param timeout + * Timeout, in milliseconds. + * @return The message. + * @throws InterruptedException + * If communications are interrupted. + * @throws SocketTimeoutException + * If a timeout happens. + */ + static ByteBuffer receiveHelper(BlockingQueue received, + long timeout) throws SocketTimeoutException, InterruptedException { + var msg = received.poll(timeout, MILLISECONDS); + if (isNull(msg)) { + throw new SocketTimeoutException(); + } + return msg; + } + + /** + * Add a {@code /} to the end of the path part of a URI. + * + * @param uri + * The URI to amend. Assumed to be HTTP or HTTPS. + * @return The amended URI. + */ + static URI asDir(URI uri) { + var path = uri.getPath(); + if (!path.endsWith("/")) { + path += "/"; + uri = uri.resolve(path); + } + return uri; + } + + /** + * Make a read-only shallow copy of a list. + * + * @param + * The type of elements in the list. These are + * recommended to be immutable, but this is not + * enforced. + * @param list + * The list to make a read-only copy of. The elements in the list + * are not themselves copied. + * @return The read-only copy. + */ + static List readOnlyCopy(List list) { + return Objects.isNull(list) ? List.of() : List.copyOf(list); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java index 982859134c..f64da3be11 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedBootConnection.java @@ -1,104 +1,104 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; -import static java.util.Objects.requireNonNull; -import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO; - -import java.io.EOFException; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.BootConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; - -/** A boot connection that routes messages across the proxy. */ -final class ProxiedBootConnection extends BootConnection { - /** The port of the connection. */ - private static final int BOOT_PORT = 54321; - - private final ProxyProtocolClient.ConnectedChannel channel; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - /** - * @param ws - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If interrupted while things were setting up. - */ - ProxiedBootConnection(ProxyProtocolClient ws) - throws IOException, InterruptedException { - this.ws = requireNonNull(ws); - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openChannel(ZERO_ZERO, BOOT_PORT, receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - protected void doSend(ByteBuffer buffer) throws IOException { - channel.send(buffer); - } - - @Override - @DoNotCall - protected void doSendTo(ByteBuffer data, InetAddress address, int port) { - throw new UnsupportedOperationException( - "sendTo() not supported by this connection type"); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; +import static java.util.Objects.requireNonNull; +import static uk.ac.manchester.spinnaker.machine.ChipLocation.ZERO_ZERO; + +import java.io.EOFException; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.BootConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; + +/** A boot connection that routes messages across the proxy. */ +final class ProxiedBootConnection extends BootConnection { + /** The port of the connection. */ + private static final int BOOT_PORT = 54321; + + private final ProxyProtocolClient.ConnectedChannel channel; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + /** + * @param ws + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If interrupted while things were setting up. + */ + ProxiedBootConnection(ProxyProtocolClient ws) + throws IOException, InterruptedException { + this.ws = requireNonNull(ws); + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openChannel(ZERO_ZERO, BOOT_PORT, receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + protected void doSend(ByteBuffer buffer) throws IOException { + channel.send(buffer); + } + + @Override + @DoNotCall + protected void doSendTo(ByteBuffer data, InetAddress address, int port) { + throw new UnsupportedOperationException( + "sendTo() not supported by this connection type"); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java index 5a9a8a66e7..1e4d00b773 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedEIEIOListenerConnection.java @@ -1,97 +1,97 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; - -import java.io.EOFException; -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.EIEIOConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -final class ProxiedEIEIOListenerConnection extends EIEIOConnection { - private final Map hostToChip; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - private ProxyProtocolClient.UnconnectedChannel channel; - - ProxiedEIEIOListenerConnection(Map hostToChip, - ProxyProtocolClient proxy) - throws InterruptedException { - this.hostToChip = hostToChip; - this.ws = proxy; - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openUnconnectedChannel(receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - @DoNotCall - protected void doSend(ByteBuffer buffer) { - throw new UnsupportedOperationException(); - } - - @Override - protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) - throws IOException { - channel.send(hostToChip.get(addr), port, buffer); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; + +import java.io.EOFException; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.EIEIOConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +final class ProxiedEIEIOListenerConnection extends EIEIOConnection { + private final Map hostToChip; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + private ProxyProtocolClient.UnconnectedChannel channel; + + ProxiedEIEIOListenerConnection(Map hostToChip, + ProxyProtocolClient proxy) + throws InterruptedException { + this.hostToChip = hostToChip; + this.ws = proxy; + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openUnconnectedChannel(receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + @DoNotCall + protected void doSend(ByteBuffer buffer) { + throw new UnsupportedOperationException(); + } + + @Override + protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) + throws IOException { + channel.send(hostToChip.get(addr), port, buffer); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java index 49be9cc27c..86a7aa0bb7 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedSCPConnection.java @@ -1,115 +1,115 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.util.Objects.isNull; - -import java.io.EOFException; -import java.io.IOException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import com.google.errorprone.annotations.DoNotCall; - -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.connections.UDPPacket; -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** An SCP connection that routes messages across the proxy. */ -final class ProxiedSCPConnection extends SCPConnection { - /** The port of the connection. */ - private static final int SCP_SCAMP_PORT = 17893; - - private final ProxyProtocolClient.ConnectedChannel channel; - - private final BlockingQueue receiveQueue; - - private ProxyProtocolClient ws; - - /** - * @param chip - * Which ethernet chip in the job are we talking to? - * @param ws - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If interrupted while things were setting up. - */ - ProxiedSCPConnection(ChipLocation chip, ProxyProtocolClient ws) - throws IOException, InterruptedException { - super(chip); - this.ws = ws; - receiveQueue = new LinkedBlockingQueue<>(); - channel = ws.openChannel(chip, SCP_SCAMP_PORT, receiveQueue); - } - - @Override - @SuppressWarnings("MissingSuperCall") - public void close() throws IOException { - channel.close(); - ws = null; - } - - @Override - public boolean isClosed() { - return isNull(ws) || !ws.isOpen(); - } - - @Override - public boolean isConnected() { - return !isClosed(); - } - - @Override - protected void doSend(ByteBuffer buffer) throws IOException { - channel.send(buffer); - } - - @Override - @DoNotCall - protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) - throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - protected ByteBuffer doReceive(int timeout) - throws IOException, InterruptedException { - if (isClosed() && receiveQueue.isEmpty()) { - throw new EOFException("connection closed"); - } - return ClientUtils.receiveHelper(receiveQueue, timeout); - } - - @Override - @DoNotCall - protected UDPPacket doReceiveWithAddress(int timeout) { - throw new UnsupportedOperationException( - "receiveWithAddress() not supported by this connection type"); - } - - /** - * Close this connection eventually. Actually processes it immediately - * because the other end of the proxy makes it eventual. - */ - @Override - public void closeEventually() { - closeAndLogNoExcept(); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.util.Objects.isNull; + +import java.io.EOFException; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import com.google.errorprone.annotations.DoNotCall; + +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.connections.UDPPacket; +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** An SCP connection that routes messages across the proxy. */ +final class ProxiedSCPConnection extends SCPConnection { + /** The port of the connection. */ + private static final int SCP_SCAMP_PORT = 17893; + + private final ProxyProtocolClient.ConnectedChannel channel; + + private final BlockingQueue receiveQueue; + + private ProxyProtocolClient ws; + + /** + * @param chip + * Which ethernet chip in the job are we talking to? + * @param ws + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If interrupted while things were setting up. + */ + ProxiedSCPConnection(ChipLocation chip, ProxyProtocolClient ws) + throws IOException, InterruptedException { + super(chip); + this.ws = ws; + receiveQueue = new LinkedBlockingQueue<>(); + channel = ws.openChannel(chip, SCP_SCAMP_PORT, receiveQueue); + } + + @Override + @SuppressWarnings("MissingSuperCall") + public void close() throws IOException { + channel.close(); + ws = null; + } + + @Override + public boolean isClosed() { + return isNull(ws) || !ws.isOpen(); + } + + @Override + public boolean isConnected() { + return !isClosed(); + } + + @Override + protected void doSend(ByteBuffer buffer) throws IOException { + channel.send(buffer); + } + + @Override + @DoNotCall + protected void doSendTo(ByteBuffer buffer, InetAddress addr, int port) + throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + protected ByteBuffer doReceive(int timeout) + throws IOException, InterruptedException { + if (isClosed() && receiveQueue.isEmpty()) { + throw new EOFException("connection closed"); + } + return ClientUtils.receiveHelper(receiveQueue, timeout); + } + + @Override + @DoNotCall + protected UDPPacket doReceiveWithAddress(int timeout) { + throw new UnsupportedOperationException( + "receiveWithAddress() not supported by this connection type"); + } + + /** + * Close this connection eventually. Actually processes it immediately + * because the other end of the proxy makes it eventual. + */ + @Override + public void closeEventually() { + closeAndLogNoExcept(); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java index 8c751f61ca..1d06160eea 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxiedTransceiver.java @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static uk.ac.manchester.spinnaker.machine.MachineVersion.TRIAD_NO_WRAPAROUND; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.Collection; -import java.util.Map; - -import uk.ac.manchester.spinnaker.connections.EIEIOConnection; -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.connections.model.Connection; -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.transceiver.SpinnmanException; -import uk.ac.manchester.spinnaker.transceiver.Transceiver; - -/** A transceiver that routes messages across the proxy. */ -final class ProxiedTransceiver extends Transceiver { - private final ProxyProtocolClient websocket; - - private final Map hostToChip; - - /** - * @param connections - * The proxied connections we will use. - * @param hostToChip - * The mapping from addresses to chip locations, to enable - * manufacturing of proxied {@link EIEIOConnection}s. - * @param websocket - * The proxy handle. - * @throws IOException - * If we couldn't finish setting up our networking. - * @throws InterruptedException - * If communications are interrupted. - * @throws SpinnmanExcception - * If SpiNNaker rejects a message. - */ - ProxiedTransceiver(Collection connections, - Map hostToChip, - ProxyProtocolClient websocket) - throws IOException, SpinnmanException, InterruptedException { - // Assume unwrapped - super(TRIAD_NO_WRAPAROUND, connections, null, null, null, null, - null); - this.hostToChip = hostToChip; - this.websocket = websocket; - } - - /** {@inheritDoc} */ - @Override - public void close() throws IOException { - super.close(); - websocket.close(); - } - - @Override - public SCPConnection createScpConnection(ChipLocation chip, - InetAddress addr) throws IOException { - try { - return new ProxiedSCPConnection(chip, websocket); - } catch (InterruptedException e) { - throw new IOException("failed to proxy connection", e); - } - } - - @Override - protected EIEIOConnection newEieioConnection(InetAddress localHost, - Integer localPort) throws IOException { - try { - return new ProxiedEIEIOListenerConnection(hostToChip, websocket); - } catch (InterruptedException e) { - throw new IOException("failed to proxy connection", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static uk.ac.manchester.spinnaker.machine.MachineVersion.TRIAD_NO_WRAPAROUND; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.util.Collection; +import java.util.Map; + +import uk.ac.manchester.spinnaker.connections.EIEIOConnection; +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.connections.model.Connection; +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.transceiver.SpinnmanException; +import uk.ac.manchester.spinnaker.transceiver.Transceiver; + +/** A transceiver that routes messages across the proxy. */ +final class ProxiedTransceiver extends Transceiver { + private final ProxyProtocolClient websocket; + + private final Map hostToChip; + + /** + * @param connections + * The proxied connections we will use. + * @param hostToChip + * The mapping from addresses to chip locations, to enable + * manufacturing of proxied {@link EIEIOConnection}s. + * @param websocket + * The proxy handle. + * @throws IOException + * If we couldn't finish setting up our networking. + * @throws InterruptedException + * If communications are interrupted. + * @throws SpinnmanExcception + * If SpiNNaker rejects a message. + */ + ProxiedTransceiver(Collection connections, + Map hostToChip, + ProxyProtocolClient websocket) + throws IOException, SpinnmanException, InterruptedException { + // Assume unwrapped + super(TRIAD_NO_WRAPAROUND, connections, null, null, null, null, + null); + this.hostToChip = hostToChip; + this.websocket = websocket; + } + + /** {@inheritDoc} */ + @Override + public void close() throws IOException { + super.close(); + websocket.close(); + } + + @Override + public SCPConnection createScpConnection(ChipLocation chip, + InetAddress addr) throws IOException { + try { + return new ProxiedSCPConnection(chip, websocket); + } catch (InterruptedException e) { + throw new IOException("failed to proxy connection", e); + } + } + + @Override + protected EIEIOConnection newEieioConnection(InetAddress localHost, + Integer localPort) throws IOException { + try { + return new ProxiedEIEIOListenerConnection(hostToChip, websocket); + } catch (InterruptedException e) { + throw new IOException("failed to proxy connection", e); + } + } +} 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 db4da86fc5..67ee75b81a 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 @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -import java.nio.ByteBuffer; - -/** Message IDs in the proxy protocol. */ -enum ProxyProtocol { - /** Open a connected channel, or its response. Two-way. */ - OPEN(20), - /** Close a channel, or its response. Two-way. */ - CLOSE(12), - /** Send a message on a connected channel, or receive a message. One-way. */ - MSG(1600), - /** Open an unconnected channel, or its response. Two-way. */ - OPEN_U(8), - /** Send a message on an unconnected channel. Never received. One-way. */ - MSG_TO(1600); - - private final int size; - - ProxyProtocol(int size) { - this.size = size; - } - - /** - * Create a buffer big enough to hold a message and fill the first word with - * the protocol ID. - * - * @return A little endian buffer of sufficient size. Position will be after - * first word. - */ - ByteBuffer allocate() { - var b = ByteBuffer.allocate(size).order(LITTLE_ENDIAN); - b.putInt(ordinal()); - return b; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import static java.nio.ByteOrder.LITTLE_ENDIAN; + +import java.nio.ByteBuffer; + +/** Message IDs in the proxy protocol. */ +enum ProxyProtocol { + /** Open a connected channel, or its response. Two-way. */ + OPEN(20), + /** Close a channel, or its response. Two-way. */ + CLOSE(12), + /** Send a message on a connected channel, or receive a message. One-way. */ + MSG(1600), + /** Open an unconnected channel, or its response. Two-way. */ + OPEN_U(8), + /** Send a message on an unconnected channel. Never received. One-way. */ + MSG_TO(1600); + + private final int size; + + ProxyProtocol(int size) { + this.size = size; + } + + /** + * Create a buffer big enough to hold a message and fill the first word with + * the protocol ID. + * + * @return A little endian buffer of sufficient size. Position will be after + * first word. + */ + ByteBuffer allocate() { + var b = ByteBuffer.allocate(size).order(LITTLE_ENDIAN); + b.putInt(ordinal()); + return b; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java index d2ebbd499b..46c7c96d4f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/ProxyProtocolClient.java @@ -1,116 +1,116 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.client; - -import java.io.Closeable; -import java.io.IOException; -import java.net.Inet4Address; -import java.nio.ByteBuffer; -import java.util.concurrent.BlockingQueue; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; - -/** - * Our interface that specifies what top-level operations can be done by the UDP - * socket proxying system. Used to hide the details of the websocket from code - * that doesn't need to care and shouldn't care. - */ -interface ProxyProtocolClient extends AutoCloseable { - /** - * Open a connected channel to a SpiNNaker board in the current job. - * - * @param chip - * The coordinates of the ethernet chip of the board to connect - * to. - * @param port - * The UDP port to connect to. - * @param receiveQueue - * Where to enqueue received messages. - * @return The connected channel. - * @throws InterruptedException - * If interrupted while waiting for a reply. - */ - ConnectedChannel openChannel(ChipLocation chip, int port, - BlockingQueue receiveQueue) throws InterruptedException; - - /** - * Open an unconnected channel to any SpiNNaker board in the current job. - * - * @param receiveQueue - * Where to enqueue received messages. - * @return The unconnected channel. - * @throws InterruptedException - * If interrupted while waiting for a reply. - */ - UnconnectedChannel openUnconnectedChannel( - BlockingQueue receiveQueue) throws InterruptedException; - - /** - * Is the underlying websocket in the state OPEN. - * - * @return state equals ReadyState.OPEN - */ - boolean isOpen(); - - /** - * {@inheritDoc} - *

- * Note that this may process the close asynchronously. - */ - @Override - void close(); - - interface ConnectedChannel extends Closeable { - /** - * Send a message to the board that the channel is connected to. - * - * @param msg - * The payload of the message to send. Might be a serialized - * SDP message, for example. - * @throws IOException - * If the message cannot be sent. - */ - void send(ByteBuffer msg) throws IOException; - } - - interface UnconnectedChannel extends Closeable { - /** - * @return The "local" address for this channel. - */ - Inet4Address getAddress(); - - /** - * @return The "local" port for this channel. - */ - int getPort(); - - /** - * Send a message to a board in the allocation of the current job. - * - * @param chip - * Which ethernet chip to send to. - * @param port - * Which UDP port to send to. - * @param msg - * The payload of the message to send. Might be a serialized - * SDP message, for example. - * @throws IOException - * If the message cannot be sent. - */ - void send(ChipLocation chip, int port, ByteBuffer msg) - throws IOException; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.client; + +import java.io.Closeable; +import java.io.IOException; +import java.net.Inet4Address; +import java.nio.ByteBuffer; +import java.util.concurrent.BlockingQueue; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; + +/** + * Our interface that specifies what top-level operations can be done by the UDP + * socket proxying system. Used to hide the details of the websocket from code + * that doesn't need to care and shouldn't care. + */ +interface ProxyProtocolClient extends AutoCloseable { + /** + * Open a connected channel to a SpiNNaker board in the current job. + * + * @param chip + * The coordinates of the ethernet chip of the board to connect + * to. + * @param port + * The UDP port to connect to. + * @param receiveQueue + * Where to enqueue received messages. + * @return The connected channel. + * @throws InterruptedException + * If interrupted while waiting for a reply. + */ + ConnectedChannel openChannel(ChipLocation chip, int port, + BlockingQueue receiveQueue) throws InterruptedException; + + /** + * Open an unconnected channel to any SpiNNaker board in the current job. + * + * @param receiveQueue + * Where to enqueue received messages. + * @return The unconnected channel. + * @throws InterruptedException + * If interrupted while waiting for a reply. + */ + UnconnectedChannel openUnconnectedChannel( + BlockingQueue receiveQueue) throws InterruptedException; + + /** + * Is the underlying websocket in the state OPEN. + * + * @return state equals ReadyState.OPEN + */ + boolean isOpen(); + + /** + * {@inheritDoc} + *

+ * Note that this may process the close asynchronously. + */ + @Override + void close(); + + interface ConnectedChannel extends Closeable { + /** + * Send a message to the board that the channel is connected to. + * + * @param msg + * The payload of the message to send. Might be a serialized + * SDP message, for example. + * @throws IOException + * If the message cannot be sent. + */ + void send(ByteBuffer msg) throws IOException; + } + + interface UnconnectedChannel extends Closeable { + /** + * @return The "local" address for this channel. + */ + Inet4Address getAddress(); + + /** + * @return The "local" port for this channel. + */ + int getPort(); + + /** + * Send a message to a board in the allocation of the current job. + * + * @param chip + * Which ethernet chip to send to. + * @param port + * Which UDP port to send to. + * @param msg + * The payload of the message to send. Might be a serialized + * SDP message, for example. + * @throws IOException + * If the message cannot be sent. + */ + void send(ChipLocation chip, int port, ByteBuffer msg) + throws IOException; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java index 55073e3308..a2b57e4867 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/Session.java @@ -1,200 +1,200 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.client; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URLConnection; -import java.util.concurrent.Callable; - -/** - * Operations on the low level session that are intended to be used by the - * client. - */ -interface Session { - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, String url2, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @param forStateChange - * If {@code true}, the connection will be configured so that it - * includes a relevant CSRF token. - * @return the partially-configured connection; - * {@link HttpURLConnection#setRequestMethod(String)}, - * {@link URLConnection#doOutput(boolean)} and - * {@link URLConnection#setRequestProperty(String,String)} may still - * need to be called. - * @throws IOException - * If things go wrong - */ - HttpURLConnection connection(URI url, URI url2, boolean forStateChange) - throws IOException; - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @param url2 - * Secondary URL, often a path tail and/or query suffix. - * @return the connection, which should not be used to change the service - * state. - * @throws IOException - * If things go wrong - */ - default HttpURLConnection connection(URI url, URI url2) throws IOException { - return connection(url, url2, false); - } - - /** - * Create a connection that's part of the session. - * - * @param url - * The URL (relative or absolute) for where to access. - * @return the connection, which should not be used to change the service - * state. - * @throws IOException - * If things go wrong - */ - default HttpURLConnection connection(URI url) throws IOException { - return connection(url, false); - } - - /** - * Check for and handle any session cookie changes. - *

- * Assumes that the session key is in the {@code JSESSIONID} cookie. - * - * @param conn - * Connection that's had a transaction processed. - * @return Whether the session cookie was set. Normally uninteresting. - */ - boolean trackCookie(HttpURLConnection conn); - - /** - * An action used by {@link ClientSession#withRenewal(Action) - * withRenewal()}. The action will be performed once, and if it fails with a - * permission fault, the session will be renewed and the action performed - * exactly once more. - * - * @param - * The type of the result of the action. - * @param - * The extra exceptions that may be thrown by the action. - */ - @FunctionalInterface - interface Action extends Callable { - /** - * Perform the action. - * - * @return The result of the action. - * @throws IOException - * If network I/O fails. - * @throws Exn - * If another failure happens. - */ - @Override - T call() throws Exn, IOException; - } - - /** - * Carry out an action, applying session renewal once if needed. - * - * @param - * The type of the return value. - * @param - * The extra exceptions that may be thrown by the action. - * @param action - * The action to be repeated if it fails due to session expiry. - * @return The result of the action - * @throws IOException - * If things go wrong. - * @throws Exn - * If another kind of failure happens. - */ - T withRenewal(Action action) - throws Exn, IOException; - - /** - * Discovers the root of a Spalloc service. Also sets up the true CSRF token - * handling. - * - * @return The service root information. - * @throws IOException - * If access fails. - */ - RootInfo discoverRoot() throws IOException; - - /** - * Connect a Spalloc proxy protocol websocket to the given URL. - * - * @param url - * Where the websocket connects. - * @return The connected websocket. - * @throws InterruptedException - * If interrupted during connection - * @throws IOException - * If there are network problems - * @throws RuntimeException - * For various reasons - */ - ProxyProtocolClient websocket(URI url) - throws InterruptedException, IOException; -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.client; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URLConnection; +import java.util.concurrent.Callable; + +/** + * Operations on the low level session that are intended to be used by the + * client. + */ +interface Session { + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, String url2, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @param forStateChange + * If {@code true}, the connection will be configured so that it + * includes a relevant CSRF token. + * @return the partially-configured connection; + * {@link HttpURLConnection#setRequestMethod(String)}, + * {@link URLConnection#doOutput(boolean)} and + * {@link URLConnection#setRequestProperty(String,String)} may still + * need to be called. + * @throws IOException + * If things go wrong + */ + HttpURLConnection connection(URI url, URI url2, boolean forStateChange) + throws IOException; + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @param url2 + * Secondary URL, often a path tail and/or query suffix. + * @return the connection, which should not be used to change the service + * state. + * @throws IOException + * If things go wrong + */ + default HttpURLConnection connection(URI url, URI url2) throws IOException { + return connection(url, url2, false); + } + + /** + * Create a connection that's part of the session. + * + * @param url + * The URL (relative or absolute) for where to access. + * @return the connection, which should not be used to change the service + * state. + * @throws IOException + * If things go wrong + */ + default HttpURLConnection connection(URI url) throws IOException { + return connection(url, false); + } + + /** + * Check for and handle any session cookie changes. + *

+ * Assumes that the session key is in the {@code JSESSIONID} cookie. + * + * @param conn + * Connection that's had a transaction processed. + * @return Whether the session cookie was set. Normally uninteresting. + */ + boolean trackCookie(HttpURLConnection conn); + + /** + * An action used by {@link ClientSession#withRenewal(Action) + * withRenewal()}. The action will be performed once, and if it fails with a + * permission fault, the session will be renewed and the action performed + * exactly once more. + * + * @param + * The type of the result of the action. + * @param + * The extra exceptions that may be thrown by the action. + */ + @FunctionalInterface + interface Action extends Callable { + /** + * Perform the action. + * + * @return The result of the action. + * @throws IOException + * If network I/O fails. + * @throws Exn + * If another failure happens. + */ + @Override + T call() throws Exn, IOException; + } + + /** + * Carry out an action, applying session renewal once if needed. + * + * @param + * The type of the return value. + * @param + * The extra exceptions that may be thrown by the action. + * @param action + * The action to be repeated if it fails due to session expiry. + * @return The result of the action + * @throws IOException + * If things go wrong. + * @throws Exn + * If another kind of failure happens. + */ + T withRenewal(Action action) + throws Exn, IOException; + + /** + * Discovers the root of a Spalloc service. Also sets up the true CSRF token + * handling. + * + * @return The service root information. + * @throws IOException + * If access fails. + */ + RootInfo discoverRoot() throws IOException; + + /** + * Connect a Spalloc proxy protocol websocket to the given URL. + * + * @param url + * Where the websocket connects. + * @return The connected websocket. + * @throws InterruptedException + * If interrupted during connection + * @throws IOException + * If there are network problems + * @throws RuntimeException + * For various reasons + */ + ProxyProtocolClient websocket(URI url) + throws InterruptedException, IOException; +} 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 index 234a23c507..ec7873ad73 100644 --- 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 @@ -1,45 +1,45 @@ -/* - * 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 - * - * http://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; - } -} +/* + * 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 + * + * http://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/model/Addresses.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java index eb8b554b33..60f08f38fd 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Addresses.java @@ -1,30 +1,30 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import java.net.InetAddress; - -/** - * The IP addresses associated with a SpiNNaker board. - * - * @param bmpIPAddress - * The IPv4 address of the BMP. - * @param spinIPAddress - * The IPv4 address of the managed SpiNNaker board. - * @author Donal Fellows - */ -public record Addresses(InetAddress bmpIPAddress, InetAddress spinIPAddress) { -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import java.net.InetAddress; + +/** + * The IP addresses associated with a SpiNNaker board. + * + * @param bmpIPAddress + * The IPv4 address of the BMP. + * @param spinIPAddress + * The IPv4 address of the managed SpiNNaker board. + * @author Donal Fellows + */ +public record Addresses(InetAddress bmpIPAddress, InetAddress spinIPAddress) { +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index fee6f82760..807ca75f8a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -1,553 +1,553 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import static java.lang.Integer.parseInt; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteBuffer.wrap; -import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Arrays.stream; -import static java.util.Collections.unmodifiableMap; -import static java.util.Collections.unmodifiableSet; -import static java.util.Objects.requireNonNull; -import static java.util.regex.Pattern.compile; -import static java.util.stream.Collectors.toMap; -import static java.util.stream.Collectors.toSet; -import static java.util.stream.Collectors.toUnmodifiableSet; -import static java.util.stream.IntStream.range; -import static org.apache.commons.io.IOUtils.buffer; -import static org.slf4j.LoggerFactory.getLogger; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_LINKS_PER_ROUTER; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_NUM_CORES; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.PROCESSORS_PER_CHIP; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_X_OF_ONE_BOARD; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_Y_OF_ONE_BOARD; -import static uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry.getSpinn5Geometry; -import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; -import static uk.ac.manchester.spinnaker.utils.CollectionUtils.OR; -import static uk.ac.manchester.spinnaker.utils.CollectionUtils.toEnumSet; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.util.EnumSet; -import java.util.Formatter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.validation.Valid; - -import org.slf4j.Logger; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.machine.Direction; -import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; -import uk.ac.manchester.spinnaker.machine.ValidP; -import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; - -/** - * A blacklist read off a board. Note that all chip coordinates are - * board-relative and all processor IDs are physical; the boot process applies - * blacklists before inter-board links are brought up and before the - * virtual-to-physical core mapping is established. - * - * @author Donal Fellows - */ -public final class Blacklist implements Serializable { - private static final long serialVersionUID = -7759940789892168209L; - - private static final Logger log = getLogger(Blacklist.class); - - private static final SpiNNakerTriadGeometry GEOM = getSpinn5Geometry(); - - private static final int SPINN5_CHIPS_PER_BOARD = 48; - - private static final int COORD_BITS = 3; - - private static final int COORD_MASK = (1 << COORD_BITS) - 1; - - private static final int CORE_MASK = (1 << MAX_NUM_CORES) - 1; - - private static final int LINK_MASK = (1 << MAX_LINKS_PER_ROUTER) - 1; - - private static final int PAYLOAD_BITS = - MAX_NUM_CORES + MAX_LINKS_PER_ROUTER; - - /** - * Bytes that represent the blacklist. Writability undefined. - * Endianness undefined. Position will be at the start of the - * blacklist data, which will be expected to run to the limit of the buffer - * (i.e., there are {@link Buffer#remaining()} bytes left). Access to this - * variable must be careful! - */ - @UsedInJavadocOnly(Buffer.class) - private transient ByteBuffer rawData; - - /** The blacklisted chips. */ - private Set<@Valid ChipLocation> chips = new HashSet<>(); - - /** The blacklisted cores. */ - private Map<@Valid ChipLocation, Set<@ValidP Integer>> cores = - new HashMap<>(); - - /** The blacklisted links. */ - private Map<@Valid ChipLocation, Set> links = new HashMap<>(); - - /** - * Create a blacklist from raw data. - * - * @param buffer - * The raw data to parse. - */ - public Blacklist(ByteBuffer buffer) { - var buf = requireNonNull(buffer).duplicate().order(LITTLE_ENDIAN); - rawData = buf.duplicate(); - decodeBlacklist(buf); - } - - /** - * Create a blacklist from parsed data. - * - * @param deadChips - * The set of chips that are dead. - * @param deadCores - * The set of physical core IDs that are dead on live chips. - * Should not contain any empty sets of physical core - * IDs; caller should ensure. - * @param deadLinks - * The set of link directions that are dead on live chips. - * Should not contain any empty sets of directions; - * caller should ensure. - */ - public Blacklist(Set deadChips, - Map> deadCores, - Map> deadLinks) { - chips = requireNonNull(deadChips); - // Sort the elements in each sub-collection - cores = requireNonNull(deadCores).entrySet().stream().collect( - toMap(Entry::getKey, e -> new TreeSet<>(e.getValue()))); - links = requireNonNull(deadLinks).entrySet().stream().collect( - toMap(Entry::getKey, e -> EnumSet.copyOf(e.getValue()))); - rawData = encodeBlacklist(); - } - - private ByteBuffer encodeBlacklist() { - var buf = allocate((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE) - .order(LITTLE_ENDIAN); - buf.putInt(0); // Size; filled in later - int count = 0; - for (int x = 0; x < SIZE_X_OF_ONE_BOARD; x++) { - for (int y = 0; y < SIZE_Y_OF_ONE_BOARD; y++) { - var chip = new ChipLocation(x, y); - int loc = (x << COORD_BITS) | y; - int value = 0; - if (chips.contains(chip)) { - value = CORE_MASK; - } else { - if (cores.containsKey(chip)) { - value |= cores.get(chip).stream() - .mapToInt(core -> 1 << core) // - .reduce(0, OR) & CORE_MASK; - } - if (links.containsKey(chip)) { - value |= links.get(chip).stream() - .mapToInt(linkDir -> 1 << linkDir.id) - .reduce(0, OR) << MAX_NUM_CORES; - } - } - if (value != 0) { - buf.putInt(value | loc << PAYLOAD_BITS); - count++; - } - } - } - buf.flip(); - buf.putInt(0, count); // Fill in the size now we know it - return buf; - } - - private void decodeBlacklist(ByteBuffer buf) { - var entries = buf.asIntBuffer(); - int len = entries.get(); - var done = new HashSet(); - - for (int i = 0; i < len; i++) { - int entry = entries.get(); - - // get board coordinates - int bx = (entry >> (PAYLOAD_BITS + COORD_BITS)) & COORD_MASK; - int by = (entry >> PAYLOAD_BITS) & COORD_MASK; - var b = new ChipLocation(bx, by); - - // check for repeated coordinates - if (done.contains(b)) { - log.warn("duplicate chip in blacklist file: {},{}", bx, by); - } - done.add(b); - - /* - * Check for blacklisted chips; those are the ones where all cores - * are blacklisted so no monitor is safe to bring up. - */ - int mcl = entry & CORE_MASK; - if (mcl == CORE_MASK) { - chips.add(b); - } else if (mcl != 0) { - // check for blacklisted cores - cores.put(b, - range(0, MAX_NUM_CORES) - .filter(c -> (mcl & (1 << c)) != 0) - .mapToObj(Integer::valueOf).collect(toSet())); - // check for blacklisted links - int mll = (entry >> MAX_NUM_CORES) & LINK_MASK; - if (mll != 0) { - links.put(b, - range(0, MAX_LINKS_PER_ROUTER) - .filter(c -> (mll & (1 << c)) != 0) - .mapToObj(Direction::byId) - .collect(toEnumSet(Direction.class))); - } - } - } - } - - /** - * Create a blacklist from a string. - * - * @param blacklistText - * The string to parse. - * @throws IllegalArgumentException - * If the string is badly formatted. - */ - public Blacklist(String blacklistText) { - requireNonNull(blacklistText, "blacklist text should not be null") - .lines().map(String::strip) - // Remove blank and comment lines - .filter(Blacklist::isRelevantLine) - // Parse the remaining lines - .forEach(this::parseLine); - rawData = encodeBlacklist(); - } - - /** - * Create a blacklist from a text file. - * - * @param blacklistFile - * The file to parse. - * @throws IOException - * If the file can't be read from. - * @throws IllegalArgumentException - * If the string is badly formatted. - */ - public Blacklist(File blacklistFile) throws IOException { - try (var r = - buffer(new FileReader( - requireNonNull(blacklistFile, - "blacklist filename should not be null"), - UTF_8))) { - r.lines().map(String::strip) - // Remove blank and comment lines - .filter(Blacklist::isRelevantLine) - // Parse the remaining lines - .forEach(this::parseLine); - rawData = encodeBlacklist(); - } - } - - private static boolean isRelevantLine(String s) { - return !s.isBlank() && !s.startsWith("#"); - } - - // REs from Perl code to read blacklist files - - private static final Pattern CHIP_PATTERN = compile( - "^\\s*chip\\s+(?[0-7])\\s+(?[0-7])\\s*"); - - private static final Pattern CORE_PATTERN = compile( - "core\\s+(?\\S+)\\s*"); - - private static final Pattern LINK_PATTERN = compile( - "link\\s+(?\\S+)\\s*"); - - private static final Pattern DEAD_PATTERN = compile("dead\\s*"); - - private static String deleteMatched(Matcher m) { - var sb = new StringBuilder(); - m.appendReplacement(sb, "").appendTail(sb); - return sb.toString(); - } - - private static Set parseCommaSeparatedSet(String str, - Function mapper) { - return stream(str.split(",")).map(mapper).collect(toUnmodifiableSet()); - } - - private static > Set parseCommaSeparatedSet( - String str, Function mapper, Class cls) { - return stream(str.split(",")).map(Integer::parseInt).map(mapper) - .collect(toEnumSet(cls)); - } - - /** - * Parse one non-empty non-comment line of a blacklist file. - * - * @param line - * The line's contents. - * @throws IllegalArgumentException - * On most parse errors. - * @throws ArrayIndexOutOfBoundsException - * On a bad direction. - */ - private void parseLine(String line) { - var m = CHIP_PATTERN.matcher(line); - if (!m.find()) { - throw new IllegalArgumentException("bad line: " + line); - } - int x = parseInt(m.group("x")); - int y = parseInt(m.group("y")); - var chip = new ChipLocation(x, y); - if (!GEOM.singleBoard().contains(chip)) { - throw new IllegalArgumentException("bad chip coords: " + line); - } - var rest = deleteMatched(m); - - ChipLocation dead = null; - Set deadCores = null; - Set deadLinks = null; - - // Look for patterns at start of line while we can - while (true) { - m = CORE_PATTERN.matcher(rest); - if (m.find() && deadCores == null) { - deadCores = parseCommaSeparatedSet( - m.group("cores"), Integer::parseInt); - deadCores.forEach(c -> { - if (c < 0 || c >= PROCESSORS_PER_CHIP) { - throw new IllegalArgumentException( - "bad core number: " + line); - } - }); - rest = deleteMatched(m); - continue; - } - - m = LINK_PATTERN.matcher(rest); - if (m.find() && deadLinks == null) { - deadLinks = parseCommaSeparatedSet(m.group("links"), - Direction::byId, Direction.class); - rest = deleteMatched(m); - continue; - } - - m = DEAD_PATTERN.matcher(rest); - if (m.find() && dead == null) { - dead = chip; - rest = deleteMatched(m); - continue; - } - - // All done, or error - if (!rest.isBlank()) { - // Bad line - throw new IllegalArgumentException("bad line: " + line); - } - break; - } - - if (dead != null) { - chips.add(dead); - // Mask any info from lines defined above this one - cores.remove(dead); - links.remove(dead); - } else if (!chips.contains(chip)) { - if (deadCores != null && !deadCores.isEmpty()) { - cores.computeIfAbsent(chip, __ -> new HashSet<>()) - .addAll(deadCores); - } - if (deadLinks != null && !deadLinks.isEmpty()) { - links.computeIfAbsent(chip, - __ -> EnumSet.noneOf(Direction.class)) - .addAll(deadLinks); - } - } - } - - /** - * Convert the blacklist to a string in a human-readable format. This is the - * format understood by {@link #Blacklist(String)}. - *

- * Note that the result may omit information in the original blacklist, but - * only if that would also be ignored by the string parser. - * - * @return The string form of the blacklist. - * @throws RuntimeException - * If something goes wrong. Not expected! - */ - public String render() { - try (var f = new Formatter()) { - render(f); - return f.toString(); - } - } - - private void render(Formatter out) { - for (var chip : GEOM.singleBoard()) { - if (!isChipMentioned(chip)) { - continue; - } - out.format("chip %d %d", chip.getX(), chip.getY()); - if (chips.contains(chip)) { - out.format(" dead\n"); - } else { - if (cores.containsKey(chip)) { - out.format(" core "); - var sep = ""; - for (var id : cores.get(chip)) { - out.format(sep).format(id.toString()); - sep = ","; - } - } - if (links.containsKey(chip)) { - out.format(" link "); - var sep = ""; - for (var d : links.get(chip)) { - out.format(sep).format(Integer.toString(d.id)); - sep = ","; - } - } - out.format("\n"); - } - } - } - - /** - * @return The chips on the board that are blacklisted. A chip being - * blacklisted means that its links will also be blacklisted. - */ - public Set getChips() { - return unmodifiableSet(chips); - } - - /** - * @return The cores on the board that are blacklisted where the whole chip - * is not blacklisted. Note that these are physical - * processor IDs, not logical ones. - */ - public Map> getCores() { - return unmodifiableMap(cores); - } - - /** - * @return The links on the board that are blacklisted. - */ - public Map> getLinks() { - return unmodifiableMap(links); - } - - /** - * Test if a chip is known about by the blacklist. - * - * @param chip - * The chip to look for. Coordinates must be board-local. - * @return Whether the chip is mentioned in the blacklist. That could be if - * it is blacklisted, if it has a blacklisted core, of if one of its - * links is blacklisted. - */ - public boolean isChipMentioned(ChipLocation chip) { - return chips.contains(chip) || cores.containsKey(chip) - || links.containsKey(chip); - } - - /** @return The raw blacklist data in little-endian form. Read only. */ - public ByteBuffer getRawData() { - return rawData.asReadOnlyBuffer().order(LITTLE_ENDIAN); - } - - @Override - public int hashCode() { - return Objects.hash(chips, cores, links); - } - - @Override - public boolean equals(Object object) { - return (object instanceof Blacklist other) && chips.equals(other.chips) - && cores.equals(other.cores) && links.equals(other.links); - } - - @Override - public String toString() { - var s = new StringBuilder("Blacklist("); - s.append(chips).append(", ").append(cores).append(", ").append(links); - return s.append(")").toString(); - } - - /** - * Write this object to the stream. This is standard except for the special - * handling of the raw data. - * - * @param out - * Where to write to. - * @throws IOException - * If output fails. - * @see ObjectOutputStream#defaultWriteObject() - */ - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeInt(rawData.remaining()); - if (rawData.hasArray()) { - out.write(rawData.array(), rawData.position(), rawData.remaining()); - } else { - byte[] buf = new byte[rawData.remaining()]; - rawData.duplicate().get(buf); - out.write(buf); - } - } - - /** - * Set this object up by reading from the stream. This is standard except - * for the special handling of the raw data. - * - * @param in - * Where to read from. - * @throws IOException - * If input fails. - * @throws ClassNotFoundException - * if the class of a serialized object could not be found. - * @see ObjectInputStream#defaultReadObject() - */ - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - int len = in.readInt(); - var buf = new byte[len]; - in.read(buf); - rawData = wrap(buf).order(LITTLE_ENDIAN); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import static java.lang.Integer.parseInt; +import static java.nio.ByteBuffer.allocate; +import static java.nio.ByteBuffer.wrap; +import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.stream; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.Objects.requireNonNull; +import static java.util.regex.Pattern.compile; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Collectors.toUnmodifiableSet; +import static java.util.stream.IntStream.range; +import static org.apache.commons.io.IOUtils.buffer; +import static org.slf4j.LoggerFactory.getLogger; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_LINKS_PER_ROUTER; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_NUM_CORES; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.PROCESSORS_PER_CHIP; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_X_OF_ONE_BOARD; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_Y_OF_ONE_BOARD; +import static uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry.getSpinn5Geometry; +import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; +import static uk.ac.manchester.spinnaker.utils.CollectionUtils.OR; +import static uk.ac.manchester.spinnaker.utils.CollectionUtils.toEnumSet; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.Formatter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.validation.Valid; + +import org.slf4j.Logger; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.machine.Direction; +import uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry; +import uk.ac.manchester.spinnaker.machine.ValidP; +import uk.ac.manchester.spinnaker.utils.UsedInJavadocOnly; + +/** + * A blacklist read off a board. Note that all chip coordinates are + * board-relative and all processor IDs are physical; the boot process applies + * blacklists before inter-board links are brought up and before the + * virtual-to-physical core mapping is established. + * + * @author Donal Fellows + */ +public final class Blacklist implements Serializable { + private static final long serialVersionUID = -7759940789892168209L; + + private static final Logger log = getLogger(Blacklist.class); + + private static final SpiNNakerTriadGeometry GEOM = getSpinn5Geometry(); + + private static final int SPINN5_CHIPS_PER_BOARD = 48; + + private static final int COORD_BITS = 3; + + private static final int COORD_MASK = (1 << COORD_BITS) - 1; + + private static final int CORE_MASK = (1 << MAX_NUM_CORES) - 1; + + private static final int LINK_MASK = (1 << MAX_LINKS_PER_ROUTER) - 1; + + private static final int PAYLOAD_BITS = + MAX_NUM_CORES + MAX_LINKS_PER_ROUTER; + + /** + * Bytes that represent the blacklist. Writability undefined. + * Endianness undefined. Position will be at the start of the + * blacklist data, which will be expected to run to the limit of the buffer + * (i.e., there are {@link Buffer#remaining()} bytes left). Access to this + * variable must be careful! + */ + @UsedInJavadocOnly(Buffer.class) + private transient ByteBuffer rawData; + + /** The blacklisted chips. */ + private Set<@Valid ChipLocation> chips = new HashSet<>(); + + /** The blacklisted cores. */ + private Map<@Valid ChipLocation, Set<@ValidP Integer>> cores = + new HashMap<>(); + + /** The blacklisted links. */ + private Map<@Valid ChipLocation, Set> links = new HashMap<>(); + + /** + * Create a blacklist from raw data. + * + * @param buffer + * The raw data to parse. + */ + public Blacklist(ByteBuffer buffer) { + var buf = requireNonNull(buffer).duplicate().order(LITTLE_ENDIAN); + rawData = buf.duplicate(); + decodeBlacklist(buf); + } + + /** + * Create a blacklist from parsed data. + * + * @param deadChips + * The set of chips that are dead. + * @param deadCores + * The set of physical core IDs that are dead on live chips. + * Should not contain any empty sets of physical core + * IDs; caller should ensure. + * @param deadLinks + * The set of link directions that are dead on live chips. + * Should not contain any empty sets of directions; + * caller should ensure. + */ + public Blacklist(Set deadChips, + Map> deadCores, + Map> deadLinks) { + chips = requireNonNull(deadChips); + // Sort the elements in each sub-collection + cores = requireNonNull(deadCores).entrySet().stream().collect( + toMap(Entry::getKey, e -> new TreeSet<>(e.getValue()))); + links = requireNonNull(deadLinks).entrySet().stream().collect( + toMap(Entry::getKey, e -> EnumSet.copyOf(e.getValue()))); + rawData = encodeBlacklist(); + } + + private ByteBuffer encodeBlacklist() { + var buf = allocate((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE) + .order(LITTLE_ENDIAN); + buf.putInt(0); // Size; filled in later + int count = 0; + for (int x = 0; x < SIZE_X_OF_ONE_BOARD; x++) { + for (int y = 0; y < SIZE_Y_OF_ONE_BOARD; y++) { + var chip = new ChipLocation(x, y); + int loc = (x << COORD_BITS) | y; + int value = 0; + if (chips.contains(chip)) { + value = CORE_MASK; + } else { + if (cores.containsKey(chip)) { + value |= cores.get(chip).stream() + .mapToInt(core -> 1 << core) // + .reduce(0, OR) & CORE_MASK; + } + if (links.containsKey(chip)) { + value |= links.get(chip).stream() + .mapToInt(linkDir -> 1 << linkDir.id) + .reduce(0, OR) << MAX_NUM_CORES; + } + } + if (value != 0) { + buf.putInt(value | loc << PAYLOAD_BITS); + count++; + } + } + } + buf.flip(); + buf.putInt(0, count); // Fill in the size now we know it + return buf; + } + + private void decodeBlacklist(ByteBuffer buf) { + var entries = buf.asIntBuffer(); + int len = entries.get(); + var done = new HashSet(); + + for (int i = 0; i < len; i++) { + int entry = entries.get(); + + // get board coordinates + int bx = (entry >> (PAYLOAD_BITS + COORD_BITS)) & COORD_MASK; + int by = (entry >> PAYLOAD_BITS) & COORD_MASK; + var b = new ChipLocation(bx, by); + + // check for repeated coordinates + if (done.contains(b)) { + log.warn("duplicate chip in blacklist file: {},{}", bx, by); + } + done.add(b); + + /* + * Check for blacklisted chips; those are the ones where all cores + * are blacklisted so no monitor is safe to bring up. + */ + int mcl = entry & CORE_MASK; + if (mcl == CORE_MASK) { + chips.add(b); + } else if (mcl != 0) { + // check for blacklisted cores + cores.put(b, + range(0, MAX_NUM_CORES) + .filter(c -> (mcl & (1 << c)) != 0) + .mapToObj(Integer::valueOf).collect(toSet())); + // check for blacklisted links + int mll = (entry >> MAX_NUM_CORES) & LINK_MASK; + if (mll != 0) { + links.put(b, + range(0, MAX_LINKS_PER_ROUTER) + .filter(c -> (mll & (1 << c)) != 0) + .mapToObj(Direction::byId) + .collect(toEnumSet(Direction.class))); + } + } + } + } + + /** + * Create a blacklist from a string. + * + * @param blacklistText + * The string to parse. + * @throws IllegalArgumentException + * If the string is badly formatted. + */ + public Blacklist(String blacklistText) { + requireNonNull(blacklistText, "blacklist text should not be null") + .lines().map(String::strip) + // Remove blank and comment lines + .filter(Blacklist::isRelevantLine) + // Parse the remaining lines + .forEach(this::parseLine); + rawData = encodeBlacklist(); + } + + /** + * Create a blacklist from a text file. + * + * @param blacklistFile + * The file to parse. + * @throws IOException + * If the file can't be read from. + * @throws IllegalArgumentException + * If the string is badly formatted. + */ + public Blacklist(File blacklistFile) throws IOException { + try (var r = + buffer(new FileReader( + requireNonNull(blacklistFile, + "blacklist filename should not be null"), + UTF_8))) { + r.lines().map(String::strip) + // Remove blank and comment lines + .filter(Blacklist::isRelevantLine) + // Parse the remaining lines + .forEach(this::parseLine); + rawData = encodeBlacklist(); + } + } + + private static boolean isRelevantLine(String s) { + return !s.isBlank() && !s.startsWith("#"); + } + + // REs from Perl code to read blacklist files + + private static final Pattern CHIP_PATTERN = compile( + "^\\s*chip\\s+(?[0-7])\\s+(?[0-7])\\s*"); + + private static final Pattern CORE_PATTERN = compile( + "core\\s+(?\\S+)\\s*"); + + private static final Pattern LINK_PATTERN = compile( + "link\\s+(?\\S+)\\s*"); + + private static final Pattern DEAD_PATTERN = compile("dead\\s*"); + + private static String deleteMatched(Matcher m) { + var sb = new StringBuilder(); + m.appendReplacement(sb, "").appendTail(sb); + return sb.toString(); + } + + private static Set parseCommaSeparatedSet(String str, + Function mapper) { + return stream(str.split(",")).map(mapper).collect(toUnmodifiableSet()); + } + + private static > Set parseCommaSeparatedSet( + String str, Function mapper, Class cls) { + return stream(str.split(",")).map(Integer::parseInt).map(mapper) + .collect(toEnumSet(cls)); + } + + /** + * Parse one non-empty non-comment line of a blacklist file. + * + * @param line + * The line's contents. + * @throws IllegalArgumentException + * On most parse errors. + * @throws ArrayIndexOutOfBoundsException + * On a bad direction. + */ + private void parseLine(String line) { + var m = CHIP_PATTERN.matcher(line); + if (!m.find()) { + throw new IllegalArgumentException("bad line: " + line); + } + int x = parseInt(m.group("x")); + int y = parseInt(m.group("y")); + var chip = new ChipLocation(x, y); + if (!GEOM.singleBoard().contains(chip)) { + throw new IllegalArgumentException("bad chip coords: " + line); + } + var rest = deleteMatched(m); + + ChipLocation dead = null; + Set deadCores = null; + Set deadLinks = null; + + // Look for patterns at start of line while we can + while (true) { + m = CORE_PATTERN.matcher(rest); + if (m.find() && deadCores == null) { + deadCores = parseCommaSeparatedSet( + m.group("cores"), Integer::parseInt); + deadCores.forEach(c -> { + if (c < 0 || c >= PROCESSORS_PER_CHIP) { + throw new IllegalArgumentException( + "bad core number: " + line); + } + }); + rest = deleteMatched(m); + continue; + } + + m = LINK_PATTERN.matcher(rest); + if (m.find() && deadLinks == null) { + deadLinks = parseCommaSeparatedSet(m.group("links"), + Direction::byId, Direction.class); + rest = deleteMatched(m); + continue; + } + + m = DEAD_PATTERN.matcher(rest); + if (m.find() && dead == null) { + dead = chip; + rest = deleteMatched(m); + continue; + } + + // All done, or error + if (!rest.isBlank()) { + // Bad line + throw new IllegalArgumentException("bad line: " + line); + } + break; + } + + if (dead != null) { + chips.add(dead); + // Mask any info from lines defined above this one + cores.remove(dead); + links.remove(dead); + } else if (!chips.contains(chip)) { + if (deadCores != null && !deadCores.isEmpty()) { + cores.computeIfAbsent(chip, __ -> new HashSet<>()) + .addAll(deadCores); + } + if (deadLinks != null && !deadLinks.isEmpty()) { + links.computeIfAbsent(chip, + __ -> EnumSet.noneOf(Direction.class)) + .addAll(deadLinks); + } + } + } + + /** + * Convert the blacklist to a string in a human-readable format. This is the + * format understood by {@link #Blacklist(String)}. + *

+ * Note that the result may omit information in the original blacklist, but + * only if that would also be ignored by the string parser. + * + * @return The string form of the blacklist. + * @throws RuntimeException + * If something goes wrong. Not expected! + */ + public String render() { + try (var f = new Formatter()) { + render(f); + return f.toString(); + } + } + + private void render(Formatter out) { + for (var chip : GEOM.singleBoard()) { + if (!isChipMentioned(chip)) { + continue; + } + out.format("chip %d %d", chip.getX(), chip.getY()); + if (chips.contains(chip)) { + out.format(" dead\n"); + } else { + if (cores.containsKey(chip)) { + out.format(" core "); + var sep = ""; + for (var id : cores.get(chip)) { + out.format(sep).format(id.toString()); + sep = ","; + } + } + if (links.containsKey(chip)) { + out.format(" link "); + var sep = ""; + for (var d : links.get(chip)) { + out.format(sep).format(Integer.toString(d.id)); + sep = ","; + } + } + out.format("\n"); + } + } + } + + /** + * @return The chips on the board that are blacklisted. A chip being + * blacklisted means that its links will also be blacklisted. + */ + public Set getChips() { + return unmodifiableSet(chips); + } + + /** + * @return The cores on the board that are blacklisted where the whole chip + * is not blacklisted. Note that these are physical + * processor IDs, not logical ones. + */ + public Map> getCores() { + return unmodifiableMap(cores); + } + + /** + * @return The links on the board that are blacklisted. + */ + public Map> getLinks() { + return unmodifiableMap(links); + } + + /** + * Test if a chip is known about by the blacklist. + * + * @param chip + * The chip to look for. Coordinates must be board-local. + * @return Whether the chip is mentioned in the blacklist. That could be if + * it is blacklisted, if it has a blacklisted core, of if one of its + * links is blacklisted. + */ + public boolean isChipMentioned(ChipLocation chip) { + return chips.contains(chip) || cores.containsKey(chip) + || links.containsKey(chip); + } + + /** @return The raw blacklist data in little-endian form. Read only. */ + public ByteBuffer getRawData() { + return rawData.asReadOnlyBuffer().order(LITTLE_ENDIAN); + } + + @Override + public int hashCode() { + return Objects.hash(chips, cores, links); + } + + @Override + public boolean equals(Object object) { + return (object instanceof Blacklist other) && chips.equals(other.chips) + && cores.equals(other.cores) && links.equals(other.links); + } + + @Override + public String toString() { + var s = new StringBuilder("Blacklist("); + s.append(chips).append(", ").append(cores).append(", ").append(links); + return s.append(")").toString(); + } + + /** + * Write this object to the stream. This is standard except for the special + * handling of the raw data. + * + * @param out + * Where to write to. + * @throws IOException + * If output fails. + * @see ObjectOutputStream#defaultWriteObject() + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeInt(rawData.remaining()); + if (rawData.hasArray()) { + out.write(rawData.array(), rawData.position(), rawData.remaining()); + } else { + byte[] buf = new byte[rawData.remaining()]; + rawData.duplicate().get(buf); + out.write(buf); + } + } + + /** + * Set this object up by reading from the stream. This is standard except + * for the special handling of the raw data. + * + * @param in + * Where to read from. + * @throws IOException + * If input fails. + * @throws ClassNotFoundException + * if the class of a serialized object could not be found. + * @see ObjectInputStream#defaultReadObject() + */ + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + int len = in.readInt(); + var buf = new byte[len]; + in.read(buf); + rawData = wrap(buf).order(LITTLE_ENDIAN); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java index ca0197b1dc..f7c40d9bbf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/SerialVector.java @@ -1,78 +1,78 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import java.nio.IntBuffer; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.messages.bmp.ReadADC; -import uk.ac.manchester.spinnaker.messages.bmp.ReadSerialVector; - -/** - * The data in the BMP serial vector. - *

- * See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. - * - * @param hardwareVersion - * Hardware version. - * @param serialNumber - * LPC1768 serial number. Length {@value #SERIAL_LENGTH}. - * @param flashBuffer - * Flash buffer address. - * @param boardStat - * {@code board_stat} address for the board. See {@link ReadADC} for - * an operation that reads this. - * @param cortexBoot - * Cortex boot vector address. Can be used to determine which copy of - * the BMP code was successfully booted from. - * @see ReadSerialVector - */ -public record SerialVector(int hardwareVersion, IntBuffer serialNumber, - MemoryLocation flashBuffer, MemoryLocation boardStat, - MemoryLocation cortexBoot) { - /** The number of words in the {@link #serialNumber() serial_number}. */ - public static final int SERIAL_LENGTH = 4; - - /** - * @return The device serial number, as a read-only buffer. Length - * {@value #SERIAL_LENGTH}. - */ - // @formatter:off - /* Obtained from LPC17xx In Application Programming function 58. The API - * descriptions for these things are fairly well buried in the LPC17xx User - * Manual. This is the relevant part: - * - * Command Read device serial number - * Input Command code: 5810 - * Parameters: None - * Return Code CMD_SUCCESS | - * Result Result0: First 32-bit word of Device Identification Number - * (at the lowest address) - * Result1: Second 32-bit word of Device Identification Number - * Result2: Third 32-bit word of Device Identification Number - * Result3: Fourth 32-bit word of Device Identification Number - * Description This command is used to read the device identification - * number. The serial number may be used to uniquely identify - * a single unit among all LPC17xx devices. - * - * The four words of the result form the four words provided below, in the - * order described above (not that that typically matters). */ - // @formatter:on - public IntBuffer serialNumber() { - // Make a new instance so positions aren't shared - return serialNumber.asReadOnlyBuffer(); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import java.nio.IntBuffer; + +import uk.ac.manchester.spinnaker.machine.MemoryLocation; +import uk.ac.manchester.spinnaker.messages.bmp.ReadADC; +import uk.ac.manchester.spinnaker.messages.bmp.ReadSerialVector; + +/** + * The data in the BMP serial vector. + *

+ * See {@code cmd_bmp_info()} in {@code bmp_cmd.c}. + * + * @param hardwareVersion + * Hardware version. + * @param serialNumber + * LPC1768 serial number. Length {@value #SERIAL_LENGTH}. + * @param flashBuffer + * Flash buffer address. + * @param boardStat + * {@code board_stat} address for the board. See {@link ReadADC} for + * an operation that reads this. + * @param cortexBoot + * Cortex boot vector address. Can be used to determine which copy of + * the BMP code was successfully booted from. + * @see ReadSerialVector + */ +public record SerialVector(int hardwareVersion, IntBuffer serialNumber, + MemoryLocation flashBuffer, MemoryLocation boardStat, + MemoryLocation cortexBoot) { + /** The number of words in the {@link #serialNumber() serial_number}. */ + public static final int SERIAL_LENGTH = 4; + + /** + * @return The device serial number, as a read-only buffer. Length + * {@value #SERIAL_LENGTH}. + */ + // @formatter:off + /* Obtained from LPC17xx In Application Programming function 58. The API + * descriptions for these things are fairly well buried in the LPC17xx User + * Manual. This is the relevant part: + * + * Command Read device serial number + * Input Command code: 5810 + * Parameters: None + * Return Code CMD_SUCCESS | + * Result Result0: First 32-bit word of Device Identification Number + * (at the lowest address) + * Result1: Second 32-bit word of Device Identification Number + * Result2: Third 32-bit word of Device Identification Number + * Result3: Fourth 32-bit word of Device Identification Number + * Description This command is used to read the device identification + * number. The serial number may be used to uniquely identify + * a single unit among all LPC17xx devices. + * + * The four words of the result form the four words provided below, in the + * order described above (not that that typically matters). */ + // @formatter:on + public IntBuffer serialNumber() { + // Make a new instance so positions aren't shared + return serialNumber.asReadOnlyBuffer(); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java index f687a965c2..20e5ef668d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagDescription.java @@ -1,118 +1,118 @@ -/* - * Copyright (c) 2018-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 - * - * http://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.model; - -import java.net.InetAddress; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.machine.CoreLocation; -import uk.ac.manchester.spinnaker.machine.tags.IPTag; -import uk.ac.manchester.spinnaker.machine.tags.ReverseIPTag; -import uk.ac.manchester.spinnaker.machine.tags.Tag; - -/** - * Description of a tag. - * - * @param count - * The count of the number of packets that have been sent with the - * tag. - * @param flags - * The flags of the tag. - * @param ipAddress - * The IP address of the tag. - * @param macAddress - * The MAC address of the tag, as an array of 6 bytes. - * @param port - * The port of the tag. - * @param rxPort - * The receive port of the tag. - * @param spinCore - * The location of the core on the chip which the tag is defined on - * and where the core that handles the tag's messages resides. - * @param spinPort - * The spin-port of the IP tag. - * @param timeout - * The timeout of the tag. - * @param src - * Where did the message that we've parsed this from originate from? - * @param host - * On what SpiNNaker board did this info originate? Assumes we were - * talking directly to the board. - * @param tagId - * What tag was this info about? - * @author Donal Fellows - */ -public record TagDescription(int count, short flags, InetAddress ipAddress, - byte[] macAddress, int port, int rxPort, CoreLocation spinCore, - int spinPort, IPTagTimeOutWaitTime timeout, ChipLocation src, - InetAddress host, int tagId) { - private static final int USE_BIT = 15; - - private static final int TEMP_BIT = 14; - - private static final int ARP_BIT = 13; - - private static final int REV_BIT = 9; - - private static final int STRIP_BIT = 8; - - private boolean bitset(int bit) { - return (flags & (1 << bit)) != 0; - } - - /** @return True if the tag is marked as being in use. */ - public boolean inUse() { - return bitset(USE_BIT); - } - - /** @return True if the tag is temporary. */ - public boolean temporary() { - return bitset(TEMP_BIT); - } - - /** - * @return True if the tag is in the ARP state (where the MAC address is - * being looked up; this is a transient state so unlikely). - */ - public boolean arp() { - return bitset(ARP_BIT); - } - - /** @return True if the tag is a reverse tag. */ - public boolean reverse() { - return bitset(REV_BIT); - } - - /** @return True if the tag is to strip the SDP header. */ - public boolean strippingSDP() { - return bitset(STRIP_BIT); - } - - /** - * Get the standard tag descriptor. Not properly meaningful unless the tag - * is {@linkplain #inUse() in use}. - * - * @return The tag descriptor. May be an {@link IPTag} or a - * {@link ReverseIPTag}. - */ - public Tag tag() { - if (reverse()) { - return new ReverseIPTag(host, tagId, rxPort, spinCore, spinPort); - } else { - return new IPTag(host, src, tagId, ipAddress, port, strippingSDP()); - } - } -} +/* + * Copyright (c) 2018-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 + * + * http://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.model; + +import java.net.InetAddress; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.machine.CoreLocation; +import uk.ac.manchester.spinnaker.machine.tags.IPTag; +import uk.ac.manchester.spinnaker.machine.tags.ReverseIPTag; +import uk.ac.manchester.spinnaker.machine.tags.Tag; + +/** + * Description of a tag. + * + * @param count + * The count of the number of packets that have been sent with the + * tag. + * @param flags + * The flags of the tag. + * @param ipAddress + * The IP address of the tag. + * @param macAddress + * The MAC address of the tag, as an array of 6 bytes. + * @param port + * The port of the tag. + * @param rxPort + * The receive port of the tag. + * @param spinCore + * The location of the core on the chip which the tag is defined on + * and where the core that handles the tag's messages resides. + * @param spinPort + * The spin-port of the IP tag. + * @param timeout + * The timeout of the tag. + * @param src + * Where did the message that we've parsed this from originate from? + * @param host + * On what SpiNNaker board did this info originate? Assumes we were + * talking directly to the board. + * @param tagId + * What tag was this info about? + * @author Donal Fellows + */ +public record TagDescription(int count, short flags, InetAddress ipAddress, + byte[] macAddress, int port, int rxPort, CoreLocation spinCore, + int spinPort, IPTagTimeOutWaitTime timeout, ChipLocation src, + InetAddress host, int tagId) { + private static final int USE_BIT = 15; + + private static final int TEMP_BIT = 14; + + private static final int ARP_BIT = 13; + + private static final int REV_BIT = 9; + + private static final int STRIP_BIT = 8; + + private boolean bitset(int bit) { + return (flags & (1 << bit)) != 0; + } + + /** @return True if the tag is marked as being in use. */ + public boolean inUse() { + return bitset(USE_BIT); + } + + /** @return True if the tag is temporary. */ + public boolean temporary() { + return bitset(TEMP_BIT); + } + + /** + * @return True if the tag is in the ARP state (where the MAC address is + * being looked up; this is a transient state so unlikely). + */ + public boolean arp() { + return bitset(ARP_BIT); + } + + /** @return True if the tag is a reverse tag. */ + public boolean reverse() { + return bitset(REV_BIT); + } + + /** @return True if the tag is to strip the SDP header. */ + public boolean strippingSDP() { + return bitset(STRIP_BIT); + } + + /** + * Get the standard tag descriptor. Not properly meaningful unless the tag + * is {@linkplain #inUse() in use}. + * + * @return The tag descriptor. May be an {@link IPTag} or a + * {@link ReverseIPTag}. + */ + public Tag tag() { + if (reverse()) { + return new ReverseIPTag(host, tagId, rxPort, spinCore, spinPort); + } else { + return new IPTag(host, src, tagId, ipAddress, port, strippingSDP()); + } + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java index 01ae0f7022..34ce1cb013 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/TagInfo.java @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2018-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 - * - * http://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.model; - -import com.google.errorprone.annotations.Immutable; - -/** - * Information about a tag pool on an Ethernet-connected chip. - * - * @param transientTimeout - * The timeout for transient IP tags (i.e., responses to SCP - * commands). - * @param poolSize - * The count of the IP tag pool size. - * @param fixedSize - * The count of the number of fixed IP tag entries. - * @author Donal Fellows - */ -@Immutable -public record TagInfo(IPTagTimeOutWaitTime transientTimeout, int poolSize, - int fixedSize) { -} +/* + * Copyright (c) 2018-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 + * + * http://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.model; + +import com.google.errorprone.annotations.Immutable; + +/** + * Information about a tag pool on an Ethernet-connected chip. + * + * @param transientTimeout + * The timeout for transient IP tags (i.e., responses to SCP + * commands). + * @param poolSize + * The count of the IP tag pool size. + * @param fixedSize + * The count of the number of fixed IP tag entries. + * @author Donal Fellows + */ +@Immutable +public record TagInfo(IPTagTimeOutWaitTime transientTimeout, int poolSize, + int fixedSize) { +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java index 435c5000e6..d55231af20 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.model; - -import uk.ac.manchester.spinnaker.messages.scp.SCPResult; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * Indicate that the board (or BMP) was unable to send a message on to its - * final destination. - */ -public class UnroutableMessageException - extends UnexpectedResponseCodeException { - private static final long serialVersionUID = 2106128799950032057L; - - /** The full header from the response message. */ - public final SDPHeader header; - - /** - * @param operation - * The overall operation that we were doing. - * @param command - * The command that we were handling a response to. - * @param header - * The header that indicated a problem with routing. - */ - public UnroutableMessageException(String operation, Enum command, - SDPHeader header) { - super(operation, command, SCPResult.RC_ROUTE); - this.header = header; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.model; + +import uk.ac.manchester.spinnaker.messages.scp.SCPResult; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * Indicate that the board (or BMP) was unable to send a message on to its + * final destination. + */ +public class UnroutableMessageException + extends UnexpectedResponseCodeException { + private static final long serialVersionUID = 2106128799950032057L; + + /** The full header from the response message. */ + public final SDPHeader header; + + /** + * @param operation + * The overall operation that we were doing. + * @param command + * The command that we were handling a response to. + * @param header + * The header that indicated a problem with routing. + */ + public UnroutableMessageException(String operation, Enum command, + SDPHeader header) { + super(operation, command, SCPResult.RC_ROUTE); + this.header = header; + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java index a8d6932acb..11a3855fd6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ConnectionAwareMessage.java @@ -1,41 +1,41 @@ -/* - * 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 - * - * http://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.scp; - -import uk.ac.manchester.spinnaker.connections.SCPConnection; -import uk.ac.manchester.spinnaker.messages.SerializableMessage; - -/** - * An interface that is applied to a message when it wants to be told what - * connection it is being sent down prior to it being sent. This is intended to - * allow information about the connection to be used in producing the parsed - * response object. - * - * @author Donal Fellows - */ -public interface ConnectionAwareMessage extends SerializableMessage { - /** - * Tell the object what connection it is being sent on. This will usually - * (except during testing) be called prior to issuing the sequence number, - * but the information provided should not be used until the response is - * being parsed. - * - * @param connection - * The connection. Should not be modified by this - * method. - */ - void setConnection(SCPConnection connection); -} +/* + * 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 + * + * http://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.scp; + +import uk.ac.manchester.spinnaker.connections.SCPConnection; +import uk.ac.manchester.spinnaker.messages.SerializableMessage; + +/** + * An interface that is applied to a message when it wants to be told what + * connection it is being sent down prior to it being sent. This is intended to + * allow information about the connection to be used in producing the parsed + * response object. + * + * @author Donal Fellows + */ +public interface ConnectionAwareMessage extends SerializableMessage { + /** + * Tell the object what connection it is being sent on. This will usually + * (except during testing) be called prior to issuing the sequence number, + * but the information provided should not be used until the response is + * being parsed. + * + * @param connection + * The connection. Should not be modified by this + * method. + */ + void setConnection(SCPConnection connection); +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java index 9c23b720bc..0e82dbfdcf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/EmptyResponse.java @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2018-2019 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 - * - * http://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.scp; - -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; - -/** - * An SCP response to a request which has an empty payload. - */ -public final class EmptyResponse extends CheckOKResponse { - /** - * Create an instance. - * - * @param operation - * The overall operation that we are doing. - * @param command - * The command that we are handling a response to. - * @param buffer - * The buffer holding the response data. - * @throws UnexpectedResponseCodeException - * If the response wasn't OK. - */ - EmptyResponse(String operation, Enum command, ByteBuffer buffer) - throws UnexpectedResponseCodeException { - super(operation, command, buffer); - } -} +/* + * Copyright (c) 2018-2019 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 + * + * http://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.scp; + +import java.nio.ByteBuffer; + +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; + +/** + * An SCP response to a request which has an empty payload. + */ +public final class EmptyResponse extends CheckOKResponse { + /** + * Create an instance. + * + * @param operation + * The overall operation that we are doing. + * @param command + * The command that we are handling a response to. + * @param buffer + * The buffer holding the response data. + * @throws UnexpectedResponseCodeException + * If the response wasn't OK. + */ + EmptyResponse(String operation, Enum command, ByteBuffer buffer) + throws UnexpectedResponseCodeException { + super(operation, command, buffer); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java index 8997be7c3d..bf8317abbc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java @@ -1,86 +1,86 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -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 uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to a core using FrontEndCommon lib's simulation management - * subsystem. - * - * @param - * The type of response expected. - */ -public abstract sealed class FECRequest - extends SCPRequest< - T> permits ClearIOBUF, UpdateProvenanceAndExit, UpdateRuntime { - /** - * @param core - * Where to send the request. - * @param replyExpected - * Whether we expect a reply. - * @param command - * What command we are invoking. - */ - FECRequest(HasCoreLocation core, boolean replyExpected, - RunningCommand command) { - super(header(core, replyExpected), command, 0, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param replyExpected - * Whether we expect a reply. - * @param command - * What command we are invoking. - * @param arg1 - * Argument 1. - * @param arg2 - * Argument 2. - * @param arg3 - * Argument 3. - * @param arg4 - * Argument 4. - */ - FECRequest(HasCoreLocation core, boolean replyExpected, - RunningCommand command, int arg1, int arg2, int arg3, int arg4) { - super(header(core, replyExpected), command, arg1, arg2, arg3, - wordAsBuffer(arg4)); - } - - /** - * Make a variant of SDP header that is used to talk to running cores. - * - * @param core - * The SpiNNaker core that we want to talk to. - * @param replyExpected - * Whether we expect a reply. - * @return The SDP header. - */ - private static SDPHeader header(HasCoreLocation core, - boolean replyExpected) { - return new SDPHeader( - replyExpected ? REPLY_EXPECTED : REPLY_NOT_EXPECTED, core, - RUNNING_COMMAND_SDP_PORT); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +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 uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to a core using FrontEndCommon lib's simulation management + * subsystem. + * + * @param + * The type of response expected. + */ +public abstract sealed class FECRequest + extends SCPRequest< + T> permits ClearIOBUF, UpdateProvenanceAndExit, UpdateRuntime { + /** + * @param core + * Where to send the request. + * @param replyExpected + * Whether we expect a reply. + * @param command + * What command we are invoking. + */ + FECRequest(HasCoreLocation core, boolean replyExpected, + RunningCommand command) { + super(header(core, replyExpected), command, 0, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param replyExpected + * Whether we expect a reply. + * @param command + * What command we are invoking. + * @param arg1 + * Argument 1. + * @param arg2 + * Argument 2. + * @param arg3 + * Argument 3. + * @param arg4 + * Argument 4. + */ + FECRequest(HasCoreLocation core, boolean replyExpected, + RunningCommand command, int arg1, int arg2, int arg3, int arg4) { + super(header(core, replyExpected), command, arg1, arg2, arg3, + wordAsBuffer(arg4)); + } + + /** + * Make a variant of SDP header that is used to talk to running cores. + * + * @param core + * The SpiNNaker core that we want to talk to. + * @param replyExpected + * Whether we expect a reply. + * @return The SDP header. + */ + private static SDPHeader header(HasCoreLocation core, + boolean replyExpected) { + return new SDPHeader( + replyExpected ? REPLY_EXPECTED : REPLY_NOT_EXPECTED, core, + RUNNING_COMMAND_SDP_PORT); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java index 1d85bdeebb..a2057d2073 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FloodFillConstants.java @@ -1,41 +1,41 @@ -/* - * 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 - * - * http://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.scp; - -/** - * Various constants used in the flood fill sub-protocol. - * - * @author Donal Fellows - */ -abstract class FloodFillConstants { - private FloodFillConstants() { - } - - /** Send on all links. */ - static final int FORWARD_LINKS = 0x3F; - - /** Inter-send delay 24μs. */ - static final int DELAY = 0x18; - - /** Number of times to resend a data message. */ - static final int DATA_RESEND = 2; - - /** Initial level. (What is level?) */ - static final int INIT_LEVEL = 3; - - /** Whether to issue an ID for the fill. */ - static final int ADD_ID = 1; -} +/* + * 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 + * + * http://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.scp; + +/** + * Various constants used in the flood fill sub-protocol. + * + * @author Donal Fellows + */ +abstract class FloodFillConstants { + private FloodFillConstants() { + } + + /** Send on all links. */ + static final int FORWARD_LINKS = 0x3F; + + /** Inter-send delay 24μs. */ + static final int DELAY = 0x18; + + /** Number of times to resend a data message. */ + static final int DATA_RESEND = 2; + + /** Initial level. (What is level?) */ + static final int INIT_LEVEL = 3; + + /** Whether to issue an ID for the fill. */ + static final int ADD_ID = 1; +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java index 3280813a1e..74b99fe416 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java @@ -1,61 +1,61 @@ -/* - * 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 - * - * http://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.scp; - -import java.nio.ByteBuffer; -import java.util.function.Supplier; - -import com.google.errorprone.annotations.ForOverride; - -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; - -/** - * A response that holds a payload. - * - * @author Donal Fellows - * @param - * The type of parsed payload value. - * @param - * The type of exception thrown by the payload parser. - */ -public abstract class PayloadedResponse - extends CheckOKResponse implements Supplier { - private final T value; - - PayloadedResponse(String operation, Enum command, ByteBuffer buffer) - throws UnexpectedResponseCodeException, E { - super(operation, command, buffer); - value = parse(buffer); - } - - @Override - public final T get() { - return value; - } - - /** - * Parse the payload of a response. The buffer will be positioned after the - * checked header. - * - * @param buffer - * The buffer to parse. Little-endian. - * @return The parsed value. - * @throws E - * If parsing fails. - */ - @ForOverride - protected abstract T parse(ByteBuffer buffer) throws E; -} +/* + * 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 + * + * http://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.scp; + +import java.nio.ByteBuffer; +import java.util.function.Supplier; + +import com.google.errorprone.annotations.ForOverride; + +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; + +/** + * A response that holds a payload. + * + * @author Donal Fellows + * @param + * The type of parsed payload value. + * @param + * The type of exception thrown by the payload parser. + */ +public abstract class PayloadedResponse + extends CheckOKResponse implements Supplier { + private final T value; + + PayloadedResponse(String operation, Enum command, ByteBuffer buffer) + throws UnexpectedResponseCodeException, E { + super(operation, command, buffer); + value = parse(buffer); + } + + @Override + public final T get() { + return value; + } + + /** + * Parse the payload of a response. The buffer will be positioned after the + * checked header. + * + * @param buffer + * The buffer to parse. Little-endian. + * @return The parsed value. + * @throws E + * If parsing fails. + */ + @ForOverride + protected abstract T parse(ByteBuffer buffer) throws E; +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java index a1164e215a..b1f9421061 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReinjectorRequest.java @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_REINJECTION; - -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to an extra monitor control core to manipulate the packet - * reinjection subsystem. - * - * @param - * The type of response. - */ -public abstract sealed class ReinjectorRequest - extends SCPRequest - permits ClearReinjectionQueue, GetReinjectionStatus, - ResetReinjectionCounters, SetReinjectionPacketTypes, - SetRouterEmergencyTimeout, SetRouterTimeout { - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command) { - super(header(core), command, 0, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - * @param argument - * What argument to provide (encoded as an integer). - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, - int argument) { - super(header(core), command, argument, 0, 0, NO_DATA); - } - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - * @param argument1 - * The first argument. - * @param argument2 - * The second argument. - * @param argument3 - * The third argument. - * @param body - * Subsequent binary data. - */ - ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, - int argument1, int argument2, int argument3, ByteBuffer body) { - super(header(core), command, argument1, argument2, argument3, body); - } - - /** - * Make a variant of SDP header that talks to the packet reinjector. It - * always wants a reply and always talks to a particular SDP port - * (the port for the reinjector). - * - * @param core - * The SpiNNaker core that we want to talk to. Should be running - * the extra monitor core (not checked). - * @return The SDP header. - */ - private static SDPHeader header(HasCoreLocation core) { - return new SDPHeader(REPLY_EXPECTED, core, - EXTRA_MONITOR_CORE_REINJECTION); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_REINJECTION; + +import java.nio.ByteBuffer; + +import uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to an extra monitor control core to manipulate the packet + * reinjection subsystem. + * + * @param + * The type of response. + */ +public abstract sealed class ReinjectorRequest + extends SCPRequest + permits ClearReinjectionQueue, GetReinjectionStatus, + ResetReinjectionCounters, SetReinjectionPacketTypes, + SetRouterEmergencyTimeout, SetRouterTimeout { + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command) { + super(header(core), command, 0, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + * @param argument + * What argument to provide (encoded as an integer). + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, + int argument) { + super(header(core), command, argument, 0, 0, NO_DATA); + } + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + * @param argument1 + * The first argument. + * @param argument2 + * The second argument. + * @param argument3 + * The third argument. + * @param body + * Subsequent binary data. + */ + ReinjectorRequest(HasCoreLocation core, ReinjectorCommand command, + int argument1, int argument2, int argument3, ByteBuffer body) { + super(header(core), command, argument1, argument2, argument3, body); + } + + /** + * Make a variant of SDP header that talks to the packet reinjector. It + * always wants a reply and always talks to a particular SDP port + * (the port for the reinjector). + * + * @param core + * The SpiNNaker core that we want to talk to. Should be running + * the extra monitor core (not checked). + * @return The SDP header. + */ + private static SDPHeader header(HasCoreLocation core) { + return new SDPHeader(REPLY_EXPECTED, core, + EXTRA_MONITOR_CORE_REINJECTION); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java index 5fb1ef0da3..887b596930 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/RouterTableRequest.java @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2019-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 - * - * http://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.scp; - -import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; -import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; - -import java.nio.ByteBuffer; - -import com.google.errorprone.annotations.ForOverride; - -import uk.ac.manchester.spinnaker.machine.HasCoreLocation; -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; -import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; - -/** - * A command message to an extra monitor control core to manipulate the router - * table. - */ -public abstract sealed class RouterTableRequest - extends SCPRequest - permits LoadApplicationRoutes, LoadSystemRoutes, SaveApplicationRoutes { - private final RouterTableCommand cmd; - - /** - * @param core - * Where to send the request. - * @param command - * What command we are invoking. - */ - RouterTableRequest(HasCoreLocation core, RouterTableCommand command) { - super(header(core), command, 0, 0, 0, NO_DATA); - cmd = command; - } - - /** - * Describe the requested operation. - * - * @return A human-readable description of the operation, for failure - * reporting. - */ - @ForOverride - abstract String describe(); - - @Override - public final EmptyResponse getSCPResponse(ByteBuffer buffer) - throws UnexpectedResponseCodeException { - return new EmptyResponse(describe(), cmd, buffer); - } - - /** - * Make a variant of SDP that talks to the packet reinjector for doing - * saving and loading of multicast router tables. - * - * @param core - * The SpiNNaker core that we want to talk to. Should be running - * the extra monitor core. - * @return The SDP header. - */ - static final SDPHeader header(HasCoreLocation core) { - return new SDPHeader(REPLY_EXPECTED, core, GATHERER_DATA_SPEED_UP); - } -} +/* + * Copyright (c) 2019-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 + * + * http://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.scp; + +import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; +import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; + +import java.nio.ByteBuffer; + +import com.google.errorprone.annotations.ForOverride; + +import uk.ac.manchester.spinnaker.machine.HasCoreLocation; +import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; +import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; + +/** + * A command message to an extra monitor control core to manipulate the router + * table. + */ +public abstract sealed class RouterTableRequest + extends SCPRequest + permits LoadApplicationRoutes, LoadSystemRoutes, SaveApplicationRoutes { + private final RouterTableCommand cmd; + + /** + * @param core + * Where to send the request. + * @param command + * What command we are invoking. + */ + RouterTableRequest(HasCoreLocation core, RouterTableCommand command) { + super(header(core), command, 0, 0, 0, NO_DATA); + cmd = command; + } + + /** + * Describe the requested operation. + * + * @return A human-readable description of the operation, for failure + * reporting. + */ + @ForOverride + abstract String describe(); + + @Override + public final EmptyResponse getSCPResponse(ByteBuffer buffer) + throws UnexpectedResponseCodeException { + return new EmptyResponse(describe(), cmd, buffer); + } + + /** + * Make a variant of SDP that talks to the packet reinjector for doing + * saving and loading of multicast router tables. + * + * @param core + * The SpiNNaker core that we want to talk to. Should be running + * the extra monitor core. + * @return The SDP header. + */ + static final SDPHeader header(HasCoreLocation core) { + return new SDPHeader(REPLY_EXPECTED, core, GATHERER_DATA_SPEED_UP); + } +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java index 05fffba96a..178be898b7 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/messages/BoardLink.java @@ -1,49 +1,49 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.google.errorprone.annotations.Immutable; - -import uk.ac.manchester.spinnaker.machine.board.ValidTriadX; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadY; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadZ; - -/** - * A combination of x, y, z and a Link. - * - * @author Christian - * @param x - * The X coordinate - * @param y - * The Y coordinate - * @param z - * The Z coordinate - * @param link - * The link number - */ -@JsonPropertyOrder({ "x", "y", "z", "link" }) -@JsonFormat(shape = ARRAY) -@Immutable -public record BoardLink(@JsonProperty("x") @ValidTriadX int x, - @JsonProperty("y") @ValidTriadY int y, - @JsonProperty("z") @ValidTriadZ int z, @JsonProperty("link") int link) { - // TODO verify format and meaning. -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.google.errorprone.annotations.Immutable; + +import uk.ac.manchester.spinnaker.machine.board.ValidTriadX; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadY; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadZ; + +/** + * A combination of x, y, z and a Link. + * + * @author Christian + * @param x + * The X coordinate + * @param y + * The Y coordinate + * @param z + * The Z coordinate + * @param link + * The link number + */ +@JsonPropertyOrder({ "x", "y", "z", "link" }) +@JsonFormat(shape = ARRAY) +@Immutable +public record BoardLink(@JsonProperty("x") @ValidTriadX int x, + @JsonProperty("y") @ValidTriadY int y, + @JsonProperty("z") @ValidTriadZ int z, @JsonProperty("link") int link) { + // TODO verify format and meaning. +} diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java index ad6b9904e8..5d1238f28f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CommonMemoryLocations.java @@ -1,109 +1,109 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.transceiver; - -import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_OFFSET; -import static uk.ac.manchester.spinnaker.messages.Constants.ROUTER_REGISTER_P2P_ADDRESS; -import static uk.ac.manchester.spinnaker.messages.Constants.SYSTEM_VARIABLE_BASE_ADDRESS; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; - -/** - * Common memory locations. Note that many locations really come in both - * buffered and unbuffered varieties, but this class doesn't hold all standard - * locations and versions: - *

Buffered SDRAM means that writes go through a write buffer. - * Unbuffered means that they go directly to SDRAM. Reads are unaffected in - * general. If you are writing lots of data, it is unlikely to matter much since - * the write buffer is limited in size. Here you probably want to use Unbuffered - * anyway, as it will then block until the write is definitely done. Using - * Buffered writing means that the write may or may not have happened at the - * time of the response.
- * - * @author Donal Fellows - */ -public abstract class CommonMemoryLocations { - private CommonMemoryLocations() { - } - - /** - * Start of unbuffered access to SDRAM. Writes will block until they have - * completed. - */ - public static final MemoryLocation UNBUFFERED_SDRAM_START = - new MemoryLocation(0x60000000); - - /** Location of routing table data in transit. Reserved by SCAMP. */ - public static final MemoryLocation ROUTING_TABLE_DATA = - new MemoryLocation(0x67800000); - - /** - * Where executables are written to prior to launching them. Reserved by - * SCAMP. - */ - public static final MemoryLocation EXECUTABLE_ADDRESS = - new MemoryLocation(0x67800000); - - /** - * Start of buffered access to SDRAM. Writes will finish rapidly, but data - * may take some cycles to appear in memory. - *

- * It doesn't matter too much when working from host; the time to do the - * network communications is rather longer than the normal buffering time - * for SDRAM. - */ - public static final MemoryLocation BUFFERED_SDRAM_START = - new MemoryLocation(0x70000000); - - /** Location of the bank of memory-mapped router registers. Buffered. */ - public static final MemoryLocation ROUTER_BASE = - new MemoryLocation(0xe1000000); - - /** Location of the memory-mapped router control register (r0). */ - public static final MemoryLocation ROUTER_CONTROL = - new MemoryLocation(0xe1000000); - - /** Location of the memory-mapped router error register (r5). */ - public static final MemoryLocation ROUTER_ERROR = - new MemoryLocation(0xe1000014); - - /** - * Where to write router diagnostic counters control data to (r11). - * Unbuffered. - */ - public static final MemoryLocation ROUTER_DIAGNOSTIC_COUNTER = - new MemoryLocation(0xf100002c); - - /** Location of the memory-mapped router filtering registers (rFN). */ - public static final MemoryLocation ROUTER_FILTERS = - new MemoryLocation(0xe1000200); - - /** Location of the memory-mapped router diagnostics registers (rCN). */ - public static final MemoryLocation ROUTER_DIAGNOSTICS = - new MemoryLocation(0xe1000300); - - /** The base address of a router's P2P routing table, 3 bits per route. */ - public static final MemoryLocation ROUTER_P2P = - new MemoryLocation(ROUTER_REGISTER_P2P_ADDRESS); - - /** Where the CPU information structure is located. Buffered system RAM. */ - public static final MemoryLocation CPU_INFO = - new MemoryLocation(CPU_INFO_OFFSET); - - /** Where the system variables are located. Unbuffered system RAM. */ - public static final MemoryLocation SYS_VARS = - new MemoryLocation(SYSTEM_VARIABLE_BASE_ADDRESS); -} +/* + * Copyright (c) 2022 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 + * + * http://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.transceiver; + +import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_OFFSET; +import static uk.ac.manchester.spinnaker.messages.Constants.ROUTER_REGISTER_P2P_ADDRESS; +import static uk.ac.manchester.spinnaker.messages.Constants.SYSTEM_VARIABLE_BASE_ADDRESS; + +import uk.ac.manchester.spinnaker.machine.MemoryLocation; + +/** + * Common memory locations. Note that many locations really come in both + * buffered and unbuffered varieties, but this class doesn't hold all standard + * locations and versions: + *

Buffered SDRAM means that writes go through a write buffer. + * Unbuffered means that they go directly to SDRAM. Reads are unaffected in + * general. If you are writing lots of data, it is unlikely to matter much since + * the write buffer is limited in size. Here you probably want to use Unbuffered + * anyway, as it will then block until the write is definitely done. Using + * Buffered writing means that the write may or may not have happened at the + * time of the response.
+ * + * @author Donal Fellows + */ +public abstract class CommonMemoryLocations { + private CommonMemoryLocations() { + } + + /** + * Start of unbuffered access to SDRAM. Writes will block until they have + * completed. + */ + public static final MemoryLocation UNBUFFERED_SDRAM_START = + new MemoryLocation(0x60000000); + + /** Location of routing table data in transit. Reserved by SCAMP. */ + public static final MemoryLocation ROUTING_TABLE_DATA = + new MemoryLocation(0x67800000); + + /** + * Where executables are written to prior to launching them. Reserved by + * SCAMP. + */ + public static final MemoryLocation EXECUTABLE_ADDRESS = + new MemoryLocation(0x67800000); + + /** + * Start of buffered access to SDRAM. Writes will finish rapidly, but data + * may take some cycles to appear in memory. + *

+ * It doesn't matter too much when working from host; the time to do the + * network communications is rather longer than the normal buffering time + * for SDRAM. + */ + public static final MemoryLocation BUFFERED_SDRAM_START = + new MemoryLocation(0x70000000); + + /** Location of the bank of memory-mapped router registers. Buffered. */ + public static final MemoryLocation ROUTER_BASE = + new MemoryLocation(0xe1000000); + + /** Location of the memory-mapped router control register (r0). */ + public static final MemoryLocation ROUTER_CONTROL = + new MemoryLocation(0xe1000000); + + /** Location of the memory-mapped router error register (r5). */ + public static final MemoryLocation ROUTER_ERROR = + new MemoryLocation(0xe1000014); + + /** + * Where to write router diagnostic counters control data to (r11). + * Unbuffered. + */ + public static final MemoryLocation ROUTER_DIAGNOSTIC_COUNTER = + new MemoryLocation(0xf100002c); + + /** Location of the memory-mapped router filtering registers (rFN). */ + public static final MemoryLocation ROUTER_FILTERS = + new MemoryLocation(0xe1000200); + + /** Location of the memory-mapped router diagnostics registers (rCN). */ + public static final MemoryLocation ROUTER_DIAGNOSTICS = + new MemoryLocation(0xe1000300); + + /** The base address of a router's P2P routing table, 3 bits per route. */ + public static final MemoryLocation ROUTER_P2P = + new MemoryLocation(ROUTER_REGISTER_P2P_ADDRESS); + + /** Where the CPU information structure is located. Buffered system RAM. */ + public static final MemoryLocation CPU_INFO = + new MemoryLocation(CPU_INFO_OFFSET); + + /** Where the system variables are located. Unbuffered system RAM. */ + public static final MemoryLocation SYS_VARS = + new MemoryLocation(SYSTEM_VARIABLE_BASE_ADDRESS); +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java index a997b95037..5b073e39fc 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersion.java @@ -1,58 +1,58 @@ -/* - * 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 - * - * http://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.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - -/** - * - * @author micro - */ -public class TestVersion { - - @Test - public void testThreeUnquoted() { - var version = Version.parse("1.2.3"); - assertEquals(1, version.majorVersion()); - assertEquals(2, version.minorVersion()); - assertEquals(3, version.revision()); - } - - @Test - public void testThreeQuoted() { - var version = Version.parse("\"1.2.3\""); - assertEquals(1, version.majorVersion()); - assertEquals(2, version.minorVersion()); - assertEquals(3, version.revision()); - } - - @Test - public void testTwoUnquoted() { - var version = Version.parse("1.2"); - assertEquals(1, version.majorVersion()); - assertEquals(2, version.minorVersion()); - assertEquals(0, version.revision()); - } - - @Test - public void testOneQuoted() { - var version = Version.parse("\"1\""); - assertEquals(1, version.majorVersion()); - assertEquals(0, version.minorVersion()); - assertEquals(0, version.revision()); - } -} +/* + * 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 + * + * http://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.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * + * @author micro + */ +public class TestVersion { + + @Test + public void testThreeUnquoted() { + var version = Version.parse("1.2.3"); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(3, version.revision()); + } + + @Test + public void testThreeQuoted() { + var version = Version.parse("\"1.2.3\""); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(3, version.revision()); + } + + @Test + public void testTwoUnquoted() { + var version = Version.parse("1.2"); + assertEquals(1, version.majorVersion()); + assertEquals(2, version.minorVersion()); + assertEquals(0, version.revision()); + } + + @Test + public void testOneQuoted() { + var version = Version.parse("\"1\""); + assertEquals(1, version.majorVersion()); + assertEquals(0, version.minorVersion()); + assertEquals(0, version.revision()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java index 68c9dea330..9fa722b8df 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestClient.java @@ -67,7 +67,7 @@ static class MockCommand extends CustomIntCommand { private static final String VOID_RETURN = """ { "return": null - } + } """; @Test diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java index fce2419ca8..aa7d5cbc53 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/TestJob.java @@ -165,7 +165,7 @@ private static void assertMockServerReceived( "command": "get_job_state", "args": [123], "kwargs": {} - } + } """, received.take(), true); JSONAssert.assertEquals(""" { diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java index 079593a2a5..f4fa55598c 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardCoordinates.java @@ -1,47 +1,47 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestBoardCoordinates { - - @Test - void testFromJson() throws IOException { - var json = "[2, 4, 6]"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, BoardCoordinates.class); - assertEquals(2, fromJson.x()); - assertEquals(4, fromJson.y()); - assertEquals(6, fromJson.z()); - - var direct = new BoardCoordinates(2, 4, 6); - assertEquals(direct, fromJson); - assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestBoardCoordinates { + + @Test + void testFromJson() throws IOException { + var json = "[2, 4, 6]"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, BoardCoordinates.class); + assertEquals(2, fromJson.x()); + assertEquals(4, fromJson.y()); + assertEquals(6, fromJson.z()); + + var direct = new BoardCoordinates(2, 4, 6); + assertEquals(direct, fromJson); + assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java index a200f32e35..b685913969 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestBoardPhysicalCoordinates.java @@ -1,47 +1,47 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestBoardPhysicalCoordinates { - - @Test - void testFromJson() throws IOException { - var json = "[2, 4, 6]"; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, BoardPhysicalCoordinates.class); - assertEquals(2, fromJson.cabinet()); - assertEquals(4, fromJson.frame()); - assertEquals(6, fromJson.board()); - - var direct = new BoardPhysicalCoordinates(2, 4, 6); - assertEquals(direct, fromJson); - assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestBoardPhysicalCoordinates { + + @Test + void testFromJson() throws IOException { + var json = "[2, 4, 6]"; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, BoardPhysicalCoordinates.class); + assertEquals(2, fromJson.cabinet()); + assertEquals(4, fromJson.frame()); + assertEquals(6, fromJson.board()); + + var direct = new BoardPhysicalCoordinates(2, 4, 6); + assertEquals(direct, fromJson); + assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java index 6b24774d93..8f8bfcff65 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobDescription.java @@ -1,96 +1,96 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.hamcrest.MatcherAssert.*; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; -import java.util.List; - -import org.hamcrest.collection.IsMapContaining; -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestJobDescription { - @Test - void testOneArg() throws IOException { - var json = """ - { - "job_id": 12345, - "owner": "someone@manchester.ac.uk", - "start_time": 1.537284307847865E9, - "keepalive": 45.0, - "state": 3, - "power": true, - "args": [1], - "kwargs": { - "tags": null, - "max_dead_boards": 0, - "machine": null, - "min_ratio": 0.333, - "max_dead_links": null, - "require_torus": false - }, - "allocated_machine_name": "Spin24b-223", - "boards": [ - [1, 1, 2] - ], - "keepalivehost": "130.88.198.171" - } - """; - - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobDescription.class); - assertEquals(12345, fromJson.getJobID()); - assertEquals("someone@manchester.ac.uk", fromJson.getOwner()); - assertEquals(1.537284307847865E9, fromJson.getStartTime()); - assertEquals(45, fromJson.getKeepAlive()); - assertEquals(State.values()[3], fromJson.getState()); - assertEquals(true, fromJson.getPower()); - assertEquals(List.of(1), fromJson.getArgs()); - var map = fromJson.getKwargs(); - assertThat(map, IsMapContaining.hasEntry("tags", null)); - assertThat(map, IsMapContaining.hasEntry("max_dead_boards", 0)); - assertThat(map, IsMapContaining.hasEntry("machine", null)); - assertThat(map, IsMapContaining.hasEntry("min_ratio", 0.333)); - assertThat(map, IsMapContaining.hasEntry("max_dead_links", null)); - assertThat(map, IsMapContaining.hasEntry("require_torus", false)); - assertEquals("Spin24b-223", fromJson.getMachine()); - assertEquals(List.of(new BoardCoordinates(1, 1, 2)), - fromJson.getBoards()); - assertEquals("130.88.198.171", fromJson.getKeepAliveHost()); - } - - @Test - void testNulls() throws IOException { - var json = """ - { - "job_id": null - } - """; - - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobDescription.class); - assertEquals(0, fromJson.getJobID()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.hamcrest.MatcherAssert.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; +import java.util.List; + +import org.hamcrest.collection.IsMapContaining; +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestJobDescription { + @Test + void testOneArg() throws IOException { + var json = """ + { + "job_id": 12345, + "owner": "someone@manchester.ac.uk", + "start_time": 1.537284307847865E9, + "keepalive": 45.0, + "state": 3, + "power": true, + "args": [1], + "kwargs": { + "tags": null, + "max_dead_boards": 0, + "machine": null, + "min_ratio": 0.333, + "max_dead_links": null, + "require_torus": false + }, + "allocated_machine_name": "Spin24b-223", + "boards": [ + [1, 1, 2] + ], + "keepalivehost": "130.88.198.171" + } + """; + + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobDescription.class); + assertEquals(12345, fromJson.getJobID()); + assertEquals("someone@manchester.ac.uk", fromJson.getOwner()); + assertEquals(1.537284307847865E9, fromJson.getStartTime()); + assertEquals(45, fromJson.getKeepAlive()); + assertEquals(State.values()[3], fromJson.getState()); + assertEquals(true, fromJson.getPower()); + assertEquals(List.of(1), fromJson.getArgs()); + var map = fromJson.getKwargs(); + assertThat(map, IsMapContaining.hasEntry("tags", null)); + assertThat(map, IsMapContaining.hasEntry("max_dead_boards", 0)); + assertThat(map, IsMapContaining.hasEntry("machine", null)); + assertThat(map, IsMapContaining.hasEntry("min_ratio", 0.333)); + assertThat(map, IsMapContaining.hasEntry("max_dead_links", null)); + assertThat(map, IsMapContaining.hasEntry("require_torus", false)); + assertEquals("Spin24b-223", fromJson.getMachine()); + assertEquals(List.of(new BoardCoordinates(1, 1, 2)), + fromJson.getBoards()); + assertEquals("130.88.198.171", fromJson.getKeepAliveHost()); + } + + @Test + void testNulls() throws IOException { + var json = """ + { + "job_id": null + } + """; + + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobDescription.class); + assertEquals(0, fromJson.getJobID()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java index 2369197574..dc095a89b2 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestJobMachineInfo.java @@ -1,85 +1,85 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -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 java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestJobMachineInfo { - @Test - void testFromJson() throws IOException { - var json = """ - { - "connections": [ - [[0,0], "10.2.225.177"], - [[4,8], "10.2.225.145"], - [[0,12], "10.2.225.185"], - [[8,16], "10.2.225.121"], - [[4,20], "10.2.225.153"], - [[8,4], "10.2.225.113"] - ], - "width": 16, - "machine_name": "Spin24b-001", - "boards": [ - [2,1,1], - [2,1,0], - [2,1,2], - [2,0,2], - [2,0,1], - [2,0,0] - ], - "height": 24 - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobMachineInfo.class); - assertEquals(6, fromJson.getConnections().size()); - assertEquals(6, fromJson.getBoards().size()); - assertEquals(16, fromJson.getWidth()); - assertEquals(24, fromJson.getHeight()); - assertEquals("Spin24b-001", fromJson.getMachineName()); - } - - @Test - void testNullJson() throws IOException { - var json = """ - { - "connections": null, - "machine_name": null, - "boards": null - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobMachineInfo.class); - assertEquals(0, fromJson.getConnections().size()); - assertEquals(0, fromJson.getBoards().size()); - assertEquals(0, fromJson.getWidth()); - assertEquals(0, fromJson.getHeight()); - assertNull(fromJson.getMachineName()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +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 java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestJobMachineInfo { + @Test + void testFromJson() throws IOException { + var json = """ + { + "connections": [ + [[0,0], "10.2.225.177"], + [[4,8], "10.2.225.145"], + [[0,12], "10.2.225.185"], + [[8,16], "10.2.225.121"], + [[4,20], "10.2.225.153"], + [[8,4], "10.2.225.113"] + ], + "width": 16, + "machine_name": "Spin24b-001", + "boards": [ + [2,1,1], + [2,1,0], + [2,1,2], + [2,0,2], + [2,0,1], + [2,0,0] + ], + "height": 24 + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobMachineInfo.class); + assertEquals(6, fromJson.getConnections().size()); + assertEquals(6, fromJson.getBoards().size()); + assertEquals(16, fromJson.getWidth()); + assertEquals(24, fromJson.getHeight()); + assertEquals("Spin24b-001", fromJson.getMachineName()); + } + + @Test + void testNullJson() throws IOException { + var json = """ + { + "connections": null, + "machine_name": null, + "boards": null + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobMachineInfo.class); + assertEquals(0, fromJson.getConnections().size()); + assertEquals(0, fromJson.getBoards().size()); + assertEquals(0, fromJson.getWidth()); + assertEquals(0, fromJson.getHeight()); + assertNull(fromJson.getMachineName()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java index 84757a1c69..7b931c2727 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestMachine.java @@ -1,120 +1,120 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.Matchers.*; -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestMachine { - - @Test - void testFromJson() throws IOException { - var json = """ - { - "name": "power-monitor", - "tags": [ - "power-monitor", - "machine-room" - ], - "width": 1, - "height":1, - "dead_boards":[ - [0,0,1], - [0,0,2] - ], - "dead_links": [] - }" - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertEquals("power-monitor", fromJson.getName()); - assertThat(fromJson.getTags(), - contains("power-monitor", "machine-room")); - assertEquals(1, fromJson.getWidth()); - assertEquals(1, fromJson.getHeight()); - assertThat(fromJson.getDeadBoards(), contains( - new BoardCoordinates(0, 0, 1), new BoardCoordinates(0, 0, 2))); - assertEquals(0, fromJson.getDeadLinks().size()); - assertNotNull(fromJson.toString()); - } - - @Test - void testAssumedDeadLinks() throws IOException { - var json = """ - { - "name": "power-monitor", - "tags": [ - "power-monitor", - "machine-room" - ], - "width": 1, - "height": 1, - "dead_boards": [ - [1,2,3], - [4,5,6] - ], - "dead_links": [ - [7,8,9,10], - [11,12,13,14] - ] - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertEquals("power-monitor", fromJson.getName()); - assertThat(fromJson.getTags(), - contains("power-monitor", "machine-room")); - assertEquals(1, fromJson.getWidth()); - assertEquals(1, fromJson.getHeight()); - assertThat(fromJson.getDeadBoards(), contains( - new BoardCoordinates(1, 2, 3), new BoardCoordinates(4, 5, 6))); - assertEquals(2, fromJson.getDeadLinks().size()); - assertEquals(7, fromJson.getDeadLinks().get(0).x()); - assertEquals(14, fromJson.getDeadLinks().get(1).link()); - assertNotNull(fromJson.toString()); - } - - @Test - void testNullJson() throws IOException { - var json = """ - { - "name": null - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, Machine.class); - assertNull(fromJson.getName()); - assertTrue(fromJson.getTags().isEmpty(), "must have no tags"); - assertEquals(0, fromJson.getWidth()); - assertEquals(0, fromJson.getHeight()); - assertTrue(fromJson.getDeadBoards().isEmpty(), - "must have no dead boards"); - assertTrue(fromJson.getDeadLinks().isEmpty(), - "must have no dead links"); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestMachine { + + @Test + void testFromJson() throws IOException { + var json = """ + { + "name": "power-monitor", + "tags": [ + "power-monitor", + "machine-room" + ], + "width": 1, + "height":1, + "dead_boards":[ + [0,0,1], + [0,0,2] + ], + "dead_links": [] + }" + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertEquals("power-monitor", fromJson.getName()); + assertThat(fromJson.getTags(), + contains("power-monitor", "machine-room")); + assertEquals(1, fromJson.getWidth()); + assertEquals(1, fromJson.getHeight()); + assertThat(fromJson.getDeadBoards(), contains( + new BoardCoordinates(0, 0, 1), new BoardCoordinates(0, 0, 2))); + assertEquals(0, fromJson.getDeadLinks().size()); + assertNotNull(fromJson.toString()); + } + + @Test + void testAssumedDeadLinks() throws IOException { + var json = """ + { + "name": "power-monitor", + "tags": [ + "power-monitor", + "machine-room" + ], + "width": 1, + "height": 1, + "dead_boards": [ + [1,2,3], + [4,5,6] + ], + "dead_links": [ + [7,8,9,10], + [11,12,13,14] + ] + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertEquals("power-monitor", fromJson.getName()); + assertThat(fromJson.getTags(), + contains("power-monitor", "machine-room")); + assertEquals(1, fromJson.getWidth()); + assertEquals(1, fromJson.getHeight()); + assertThat(fromJson.getDeadBoards(), contains( + new BoardCoordinates(1, 2, 3), new BoardCoordinates(4, 5, 6))); + assertEquals(2, fromJson.getDeadLinks().size()); + assertEquals(7, fromJson.getDeadLinks().get(0).x()); + assertEquals(14, fromJson.getDeadLinks().get(1).link()); + assertNotNull(fromJson.toString()); + } + + @Test + void testNullJson() throws IOException { + var json = """ + { + "name": null + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, Machine.class); + assertNull(fromJson.getName()); + assertTrue(fromJson.getTags().isEmpty(), "must have no tags"); + assertEquals(0, fromJson.getWidth()); + assertEquals(0, fromJson.getHeight()); + assertTrue(fromJson.getDeadBoards().isEmpty(), + "must have no dead boards"); + assertTrue(fromJson.getDeadLinks().isEmpty(), + "must have no dead links"); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java index 6bb773c21e..00dc7dd0cc 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestState.java @@ -1,71 +1,71 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author Christian - */ -public class TestState { - - @Test - void testFromJson() throws IOException { - var json = """ - { - "state": 2, - "power": true, - "keepalive": 60.0, - "reason": null, - "start_time": 1.125, - "keepalivehost": "86.82.216.229" - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobState.class); - assertEquals(State.POWER, fromJson.getState()); - assertEquals(true, fromJson.getPower()); - assertEquals(1.125, fromJson.getStartTime()); - assertEquals(60, fromJson.getKeepalive()); - assertNull(fromJson.getReason()); - assertEquals("86.82.216.229", fromJson.getKeepalivehost()); - assertNotNull(fromJson.toString()); - } - - @Test - void testNullJson() throws IOException { - var json = """ - { - "reason": null - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, JobState.class); - assertNull(fromJson.getState()); - assertNull(fromJson.getPower()); - assertNull(fromJson.getReason()); - assertEquals(0.0, fromJson.getStartTime()); - assertNull(fromJson.getKeepalivehost()); - assertNotNull(fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author Christian + */ +public class TestState { + + @Test + void testFromJson() throws IOException { + var json = """ + { + "state": 2, + "power": true, + "keepalive": 60.0, + "reason": null, + "start_time": 1.125, + "keepalivehost": "86.82.216.229" + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobState.class); + assertEquals(State.POWER, fromJson.getState()); + assertEquals(true, fromJson.getPower()); + assertEquals(1.125, fromJson.getStartTime()); + assertEquals(60, fromJson.getKeepalive()); + assertNull(fromJson.getReason()); + assertEquals("86.82.216.229", fromJson.getKeepalivehost()); + assertNotNull(fromJson.toString()); + } + + @Test + void testNullJson() throws IOException { + var json = """ + { + "reason": null + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, JobState.class); + assertNull(fromJson.getState()); + assertNull(fromJson.getPower()); + assertNull(fromJson.getReason()); + assertEquals(0.0, fromJson.getStartTime()); + assertNull(fromJson.getKeepalivehost()); + assertNotNull(fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java index c36421591f..6e668e95af 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/spalloc/messages/TestWhereIs.java @@ -1,133 +1,133 @@ -/* - * 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 - * - * http://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.spalloc.messages; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.IOException; - -import org.junit.jupiter.api.Test; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.spalloc.SpallocClient; - -/** - * - * @author micro - */ -public class TestWhereIs { - - @Test - void testFromJson() throws IOException { - var jobChip = new ChipLocation(1, 2); - var chip = new ChipLocation(3, 4); - var boardChip = new ChipLocation(8, 9); - var logical = new BoardCoordinates(5, 6, 7); - var physical = new BoardPhysicalCoordinates(10, 11, 12); - - var json = """ - { - "job_chip": [1,2], - "job_id": 666, - "chip": [3,4], - "logical": [5,6,7], - "machine": "Spin24b-001", - "board_chip": [8,9], - "physical": [10,11,12] - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertEquals(jobChip, fromJson.jobChip()); - assertEquals(666, fromJson.jobId()); - assertEquals(chip, fromJson.chip()); - assertEquals(logical, fromJson.logical()); - assertEquals("Spin24b-001", fromJson.machine()); - assertEquals(boardChip, fromJson.boardChip()); - var physical2 = fromJson.physical(); - assertEquals(physical, physical2); - - var direct = new WhereIs(jobChip, 666, chip, logical, "Spin24b-001", - boardChip, physical); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - - @Test - void testBug() throws IOException { - var chip = new ChipLocation(8, 4); - var boardChip = new ChipLocation(0, 0); - var logical = new BoardCoordinates(0, 0, 1); - var physical = new BoardPhysicalCoordinates(0, 0, 8); - - var json = """ - { - "job_chip": null, - "job_id": null, - "chip": [8,4], - "logical": [0,0,1], - "machine": "Spin24b-001", - "board_chip": [0,0], - "physical": [0,0,8] - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.jobChip()); - assertNull(fromJson.jobId()); - assertEquals(chip, fromJson.chip()); - assertEquals(logical, fromJson.logical()); - assertEquals("Spin24b-001", fromJson.machine()); - assertEquals(boardChip, fromJson.boardChip()); - assertEquals(physical, fromJson.physical()); - - var direct = new WhereIs(null, null, chip, logical, "Spin24b-001", - boardChip, physical); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } - - @Test - void testNulls() throws IOException { - var json = """ - { - "job_chip": null, - "job_id": null, - "chip": null, - "logical": null, - "machine": null, - "board_chip": null, - "physical": null - } - """; - var mapper = SpallocClient.createMapper(); - var fromJson = mapper.readValue(json, WhereIs.class); - assertNull(fromJson.jobChip()); - assertNull(fromJson.jobId()); - assertNull(fromJson.chip()); - assertNull(fromJson.logical()); - assertNull(fromJson.machine()); - assertNull(fromJson.boardChip()); - assertNull(fromJson.physical()); - - var direct = new WhereIs(null, null, null, null, null, null, null); - assertEquals(direct, fromJson); - // assertEquals(direct.hashCode(), fromJson.hashCode()); - assertEquals(direct.toString(), fromJson.toString()); - } -} +/* + * 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 + * + * http://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.spalloc.messages; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.spalloc.SpallocClient; + +/** + * + * @author micro + */ +public class TestWhereIs { + + @Test + void testFromJson() throws IOException { + var jobChip = new ChipLocation(1, 2); + var chip = new ChipLocation(3, 4); + var boardChip = new ChipLocation(8, 9); + var logical = new BoardCoordinates(5, 6, 7); + var physical = new BoardPhysicalCoordinates(10, 11, 12); + + var json = """ + { + "job_chip": [1,2], + "job_id": 666, + "chip": [3,4], + "logical": [5,6,7], + "machine": "Spin24b-001", + "board_chip": [8,9], + "physical": [10,11,12] + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertEquals(jobChip, fromJson.jobChip()); + assertEquals(666, fromJson.jobId()); + assertEquals(chip, fromJson.chip()); + assertEquals(logical, fromJson.logical()); + assertEquals("Spin24b-001", fromJson.machine()); + assertEquals(boardChip, fromJson.boardChip()); + var physical2 = fromJson.physical(); + assertEquals(physical, physical2); + + var direct = new WhereIs(jobChip, 666, chip, logical, "Spin24b-001", + boardChip, physical); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + + @Test + void testBug() throws IOException { + var chip = new ChipLocation(8, 4); + var boardChip = new ChipLocation(0, 0); + var logical = new BoardCoordinates(0, 0, 1); + var physical = new BoardPhysicalCoordinates(0, 0, 8); + + var json = """ + { + "job_chip": null, + "job_id": null, + "chip": [8,4], + "logical": [0,0,1], + "machine": "Spin24b-001", + "board_chip": [0,0], + "physical": [0,0,8] + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertNull(fromJson.jobChip()); + assertNull(fromJson.jobId()); + assertEquals(chip, fromJson.chip()); + assertEquals(logical, fromJson.logical()); + assertEquals("Spin24b-001", fromJson.machine()); + assertEquals(boardChip, fromJson.boardChip()); + assertEquals(physical, fromJson.physical()); + + var direct = new WhereIs(null, null, chip, logical, "Spin24b-001", + boardChip, physical); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } + + @Test + void testNulls() throws IOException { + var json = """ + { + "job_chip": null, + "job_id": null, + "chip": null, + "logical": null, + "machine": null, + "board_chip": null, + "physical": null + } + """; + var mapper = SpallocClient.createMapper(); + var fromJson = mapper.readValue(json, WhereIs.class); + assertNull(fromJson.jobChip()); + assertNull(fromJson.jobId()); + assertNull(fromJson.chip()); + assertNull(fromJson.logical()); + assertNull(fromJson.machine()); + assertNull(fromJson.boardChip()); + assertNull(fromJson.physical()); + + var direct = new WhereIs(null, null, null, null, null, null, null); + assertEquals(direct, fromJson); + // assertEquals(direct.hashCode(), fromJson.hashCode()); + assertEquals(direct.toString(), fromJson.toString()); + } +} diff --git a/SpiNNaker-comms/src/test/resources/spinn2.json b/SpiNNaker-comms/src/test/resources/spinn2.json index 89e2f8bd6d..e2be180d63 100644 --- a/SpiNNaker-comms/src/test/resources/spinn2.json +++ b/SpiNNaker-comms/src/test/resources/spinn2.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-comms/src/test/resources/spinn4.json b/SpiNNaker-comms/src/test/resources/spinn4.json index 91f9918a2c..e72356b586 100644 --- a/SpiNNaker-comms/src/test/resources/spinn4.json +++ b/SpiNNaker-comms/src/test/resources/spinn4.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 18, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 18, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 18, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 18, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 18, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 18, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 18, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 18, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 18, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 18, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist b/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist index 916dee007f..a40276a0f2 100644 --- a/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist +++ b/SpiNNaker-comms/src/test/resources/uk/ac/manchester/spinnaker/alloc/bmp/example.blacklist @@ -1,18 +1,18 @@ -# Copyright (c) 2022 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 -# -# http://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. - -chip 1 1 dead -chip 1 0 core 2,3 link 4,5 -# Include some high numbers -chip 7 7 link 1,5 core 10,17 +# Copyright (c) 2022 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 +# +# http://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. + +chip 1 1 dead +chip 1 0 core 2,3 link 4,5 +# Include some high numbers +chip 7 7 link 1,5 core 10,17 diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java index 39f43a99ed..99fb0a1179 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/DebuggingUtils.java @@ -1,96 +1,96 @@ -/* - * Copyright (c) 2019-2022 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 - * - * http://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.front_end; - -import static difflib.DiffUtils.diff; -import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; -import static java.util.stream.Collectors.toList; - -import java.nio.ByteBuffer; -import java.util.List; - -import org.slf4j.Logger; - -import difflib.Chunk; -import uk.ac.manchester.spinnaker.utils.MathUtils; - -/** - * Utilities for debugging. - */ -public abstract class DebuggingUtils { - private DebuggingUtils() { - } - - /** - * Compare two buffers and write a description of how they differ to the - * given log (if they actually differ). - * - * @param original - * The data to compare against. The ground truth. - * @param downloaded - * The data that is being checked for differences. - * @param log - * Where to write messages on differences being found. - */ - public static void compareBuffers(ByteBuffer original, - ByteBuffer downloaded, Logger log) { - for (int i = 0; i < original.remaining(); i++) { - if (original.get(i) != downloaded.get(i)) { - log.error("downloaded buffer contents different"); - for (var delta : diff(list(original), list(downloaded)) - .getDeltas()) { - switch (delta.getType()) { - case CHANGE -> { - var changeFrom = delta.getOriginal(); - var changeTo = delta.getRevised(); - log.warn( - "swapped {} bytes (SCP) for {} (gather) " - + "at {}->{}", - changeFrom.getLines().size(), - changeTo.getLines().size(), - changeFrom.getPosition(), - changeTo.getPosition()); - log.info("change {} -> {}", describeChunk(changeFrom), - describeChunk(changeTo)); - } - case DELETE -> { - var delete = delta.getOriginal(); - log.warn("gather deleted {} bytes at {}", - delete.getLines().size(), delete.getPosition()); - log.info("delete {}", describeChunk(delete)); - } - default /* INSERT */ -> { - var insert = delta.getRevised(); - log.warn("gather inserted {} bytes at {}", - insert.getLines().size(), insert.getPosition()); - log.info("insert {}", describeChunk(insert)); - } - } - } - break; - } - } - } - - private static List list(ByteBuffer buffer) { - return sliceUp(buffer, 1).map(ByteBuffer::get).toList(); - } - - private static List describeChunk(Chunk chunk) { - return chunk.getLines().stream().map(MathUtils::hexbyte) - .collect(toList()); - } -} +/* + * Copyright (c) 2019-2022 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 + * + * http://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.front_end; + +import static difflib.DiffUtils.diff; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.sliceUp; +import static java.util.stream.Collectors.toList; + +import java.nio.ByteBuffer; +import java.util.List; + +import org.slf4j.Logger; + +import difflib.Chunk; +import uk.ac.manchester.spinnaker.utils.MathUtils; + +/** + * Utilities for debugging. + */ +public abstract class DebuggingUtils { + private DebuggingUtils() { + } + + /** + * Compare two buffers and write a description of how they differ to the + * given log (if they actually differ). + * + * @param original + * The data to compare against. The ground truth. + * @param downloaded + * The data that is being checked for differences. + * @param log + * Where to write messages on differences being found. + */ + public static void compareBuffers(ByteBuffer original, + ByteBuffer downloaded, Logger log) { + for (int i = 0; i < original.remaining(); i++) { + if (original.get(i) != downloaded.get(i)) { + log.error("downloaded buffer contents different"); + for (var delta : diff(list(original), list(downloaded)) + .getDeltas()) { + switch (delta.getType()) { + case CHANGE -> { + var changeFrom = delta.getOriginal(); + var changeTo = delta.getRevised(); + log.warn( + "swapped {} bytes (SCP) for {} (gather) " + + "at {}->{}", + changeFrom.getLines().size(), + changeTo.getLines().size(), + changeFrom.getPosition(), + changeTo.getPosition()); + log.info("change {} -> {}", describeChunk(changeFrom), + describeChunk(changeTo)); + } + case DELETE -> { + var delete = delta.getOriginal(); + log.warn("gather deleted {} bytes at {}", + delete.getLines().size(), delete.getPosition()); + log.info("delete {}", describeChunk(delete)); + } + default /* INSERT */ -> { + var insert = delta.getRevised(); + log.warn("gather inserted {} bytes at {}", + insert.getLines().size(), insert.getPosition()); + log.info("insert {}", describeChunk(insert)); + } + } + } + break; + } + } + } + + private static List list(ByteBuffer buffer) { + return sliceUp(buffer, 1).map(ByteBuffer::get).toList(); + } + + private static List describeChunk(Chunk chunk) { + return chunk.getLines().stream().map(MathUtils::hexbyte) + .collect(toList()); + } +} diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java index 000125a815..42e2b8ddf4 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ExecuteDataSpecification.java @@ -1,127 +1,127 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.front_end.dse; - -import static uk.ac.manchester.spinnaker.front_end.Constants.PARALLEL_SIZE; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.List; -import java.util.function.Function; - -import com.google.errorprone.annotations.MustBeClosed; - -import uk.ac.manchester.spinnaker.data_spec.DataSpecificationException; -import uk.ac.manchester.spinnaker.front_end.BasicExecutor; -import uk.ac.manchester.spinnaker.front_end.BoardLocalSupport; -import uk.ac.manchester.spinnaker.front_end.BasicExecutor.SimpleCallable; -import uk.ac.manchester.spinnaker.machine.Machine; -import uk.ac.manchester.spinnaker.storage.StorageException; -import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; -import uk.ac.manchester.spinnaker.storage.DSEStorage.Ethernet; -import uk.ac.manchester.spinnaker.transceiver.ProcessException; -import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; - -/** - * Common base for executing data specifications. - * - * @author Donal Fellows - */ -public abstract class ExecuteDataSpecification extends BoardLocalSupport - implements AutoCloseable { - /** The database. */ - protected final DSEDatabaseEngine db; - - /** How to run tasks in parallel. */ - private final BasicExecutor executor; - - /** - * @param txrx - * The transceiver for talking to the SpiNNaker machine. - * @param machine - * The description of the SpiNNaker machine. - * @param db - * The DSE database. - * @throws IOException - * If the transceiver can't talk to its sockets. - * @throws ProcessException - * If SpiNNaker rejects a message. - * @throws InterruptedException - * If communications are interrupted. - * @throws IllegalStateException - * If something really strange occurs with talking to the BMP; - * this constructor should not be doing that! - * @throws StorageException - * If the database cannot be read. - * @throws URISyntaxException - * If the proxy URI is specified but not valid. - */ - @MustBeClosed - @SuppressWarnings("MustBeClosed") - protected ExecuteDataSpecification(TransceiverInterface txrx, - Machine machine, DSEDatabaseEngine db) - throws IOException, ProcessException, InterruptedException, - StorageException, URISyntaxException { - super((db == null) ? null : txrx, machine); - this.db = db; - this.executor = new BasicExecutor(PARALLEL_SIZE); - } - - @Override - public final void close() throws IOException, InterruptedException { - if (txrx != null) { - txrx.close(); - } - executor.close(); - } - - /** - * Run the tasks in parallel. Submits to {@link #executor} and detoxifies - * the exceptions. - * - * @param tasks - * The tasks to run. - * @param mapper - * Gets how to implement a task. - * @throws StorageException - * If the database can't be talked to. - * @throws IOException - * If the transceiver can't talk to its sockets. - * @throws ProcessException - * If SpiNNaker rejects a message. - * @throws DataSpecificationException - * If a data specification in the database is invalid. - * @throws InterruptedException - * If communications are interrupted. - * @throws IllegalStateException - * If an unexpected exception occurs in any of the parallel - * tasks. - */ - protected final void processTasksInParallel(List tasks, - Function mapper) throws StorageException, - IOException, ProcessException, DataSpecificationException, - InterruptedException { - try { - executor.submitTasks(tasks, mapper).awaitAndCombineExceptions(); - } catch (StorageException | IOException | ProcessException - | DataSpecificationException | InterruptedException - | RuntimeException e) { - throw e; - } catch (Exception e) { - throw new IllegalStateException("unexpected exception", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.front_end.dse; + +import static uk.ac.manchester.spinnaker.front_end.Constants.PARALLEL_SIZE; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.List; +import java.util.function.Function; + +import com.google.errorprone.annotations.MustBeClosed; + +import uk.ac.manchester.spinnaker.data_spec.DataSpecificationException; +import uk.ac.manchester.spinnaker.front_end.BasicExecutor; +import uk.ac.manchester.spinnaker.front_end.BoardLocalSupport; +import uk.ac.manchester.spinnaker.front_end.BasicExecutor.SimpleCallable; +import uk.ac.manchester.spinnaker.machine.Machine; +import uk.ac.manchester.spinnaker.storage.StorageException; +import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; +import uk.ac.manchester.spinnaker.storage.DSEStorage.Ethernet; +import uk.ac.manchester.spinnaker.transceiver.ProcessException; +import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; + +/** + * Common base for executing data specifications. + * + * @author Donal Fellows + */ +public abstract class ExecuteDataSpecification extends BoardLocalSupport + implements AutoCloseable { + /** The database. */ + protected final DSEDatabaseEngine db; + + /** How to run tasks in parallel. */ + private final BasicExecutor executor; + + /** + * @param txrx + * The transceiver for talking to the SpiNNaker machine. + * @param machine + * The description of the SpiNNaker machine. + * @param db + * The DSE database. + * @throws IOException + * If the transceiver can't talk to its sockets. + * @throws ProcessException + * If SpiNNaker rejects a message. + * @throws InterruptedException + * If communications are interrupted. + * @throws IllegalStateException + * If something really strange occurs with talking to the BMP; + * this constructor should not be doing that! + * @throws StorageException + * If the database cannot be read. + * @throws URISyntaxException + * If the proxy URI is specified but not valid. + */ + @MustBeClosed + @SuppressWarnings("MustBeClosed") + protected ExecuteDataSpecification(TransceiverInterface txrx, + Machine machine, DSEDatabaseEngine db) + throws IOException, ProcessException, InterruptedException, + StorageException, URISyntaxException { + super((db == null) ? null : txrx, machine); + this.db = db; + this.executor = new BasicExecutor(PARALLEL_SIZE); + } + + @Override + public final void close() throws IOException, InterruptedException { + if (txrx != null) { + txrx.close(); + } + executor.close(); + } + + /** + * Run the tasks in parallel. Submits to {@link #executor} and detoxifies + * the exceptions. + * + * @param tasks + * The tasks to run. + * @param mapper + * Gets how to implement a task. + * @throws StorageException + * If the database can't be talked to. + * @throws IOException + * If the transceiver can't talk to its sockets. + * @throws ProcessException + * If SpiNNaker rejects a message. + * @throws DataSpecificationException + * If a data specification in the database is invalid. + * @throws InterruptedException + * If communications are interrupted. + * @throws IllegalStateException + * If an unexpected exception occurs in any of the parallel + * tasks. + */ + protected final void processTasksInParallel(List tasks, + Function mapper) throws StorageException, + IOException, ProcessException, DataSpecificationException, + InterruptedException { + try { + executor.submitTasks(tasks, mapper).awaitAndCombineExceptions(); + } catch (StorageException | IOException | ProcessException + | DataSpecificationException | InterruptedException + | RuntimeException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("unexpected exception", e); + } + } +} diff --git a/SpiNNaker-front-end/src/test/resources/gather.json b/SpiNNaker-front-end/src/test/resources/gather.json index 8aa16f57d5..5165c09f03 100644 --- a/SpiNNaker-front-end/src/test/resources/gather.json +++ b/SpiNNaker-front-end/src/test/resources/gather.json @@ -1 +1 @@ -[{"x": 0, "y": 0, "p": 1, "iptag": {"x": 0, "y": 0, "boardAddress": "192.168.240.253", "targetAddress": "localhost", "stripSDP": true, "tagID": 1, "trafficIdentifier": "DATA_SPEED_UP"}, "monitors": [{"x": 0, "y": 0, "p": 2, "placements": [{"x": 0, "y": 0, "p": 3, "vertex": {"label": "pop_1:0:2", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1614021536}}, {"x": 0, "y": 0, "p": 4, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972308}}]}]}] \ No newline at end of file +[{"x": 0, "y": 0, "p": 1, "iptag": {"x": 0, "y": 0, "boardAddress": "192.168.240.253", "targetAddress": "localhost", "stripSDP": true, "tagID": 1, "trafficIdentifier": "DATA_SPEED_UP"}, "monitors": [{"x": 0, "y": 0, "p": 2, "placements": [{"x": 0, "y": 0, "p": 3, "vertex": {"label": "pop_1:0:2", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1614021536}}, {"x": 0, "y": 0, "p": 4, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972308}}]}]}] diff --git a/SpiNNaker-front-end/src/test/resources/machine.json b/SpiNNaker-front-end/src/test/resources/machine.json index 2fcb2c872b..4303670184 100644 --- a/SpiNNaker-front-end/src/test/resources/machine.json +++ b/SpiNNaker-front-end/src/test/resources/machine.json @@ -1,16 +1,16 @@ -{ - "width": 1, - "height": 1, - "root": [0, 0], - "ethernetResources": {}, - "standardResources": {}, - "chips": [ - [ - 0, 0, { - "cores": 1, - "ethernet": [0, 0], - "ipAddress": "127.0.0.1" - } - ] - ] -} +{ + "width": 1, + "height": 1, + "root": [0, 0], + "ethernetResources": {}, + "standardResources": {}, + "chips": [ + [ + 0, 0, { + "cores": 1, + "ethernet": [0, 0], + "ipAddress": "127.0.0.1" + } + ] + ] +} diff --git a/SpiNNaker-front-end/src/test/resources/simple.json b/SpiNNaker-front-end/src/test/resources/simple.json index f98d2d8f46..035b20721e 100644 --- a/SpiNNaker-front-end/src/test/resources/simple.json +++ b/SpiNNaker-front-end/src/test/resources/simple.json @@ -1,2 +1,2 @@ [{"x": 0, "y": 0, "p": 1, "vertex": {"label": "pop_1:0:0", "recordedRegionIds": [0, 1], "recordingRegionBaseAddress": 1612972372}}, - {"x": 0, "y": 0, "p": 2, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972632}}] \ No newline at end of file + {"x": 0, "y": 0, "p": 2, "vertex": {"label": "input:0:0", "recordedRegionIds": [], "recordingRegionBaseAddress": 1612972632}}] diff --git a/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict b/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict index 8c67b7c3b6..2c60c4ecb5 100644 --- a/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict +++ b/SpiNNaker-front-end/src/test/resources/uk/ac/manchester/spinnaker/front_end/iobuf/empty.dict @@ -1,16 +1,16 @@ -# Copyright (c) 2022 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 -# -# http://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. -1,abc,-d-%d-e-%d-f-%d -2,abc,,d,%d,e,%d,f,%d -foo,abcde,-d-%d-e-%d-f-%d +# Copyright (c) 2022 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 +# +# http://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. +1,abc,-d-%d-e-%d-f-%d +2,abc,,d,%d,e,%d,f,%d +foo,abcde,-d-%d-e-%d-f-%d diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java index f3b3e6572d..e3154b672b 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/MemoryLocation.java @@ -1,151 +1,151 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.Integer.compareUnsigned; -import static java.lang.String.format; - -import com.google.errorprone.annotations.Immutable; - -/** - * A location in SpiNNaker or BMP memory. Does not say which address space this - * is in. - * - * @author Donal Fellows - * @param address - * The actual location. - */ -@Immutable -public record MemoryLocation(int address) - implements Comparable { - /** Number of bytes in a SpiNNaker (ARM) word. */ - private static final int WORD_SIZE = 4; - - /** The zero memory location. Often means "no actual address". */ - public static final MemoryLocation NULL = new MemoryLocation(0); - - /** - * @param address - * The actual location. - */ - public MemoryLocation(long address) { - this(convert(address)); - } - - /** - * Add an offset to this location to get a new memory location. - * - * @param offset - * The offset to add. - * @return The new memory location. - */ - public MemoryLocation add(int offset) { - return new MemoryLocation(address + offset); - } - - /** - * Get the difference between this location and another. - * - * @param other - * The other location. - * @return This location's address minus the other location's address. - */ - public int diff(MemoryLocation other) { - return address - other.address; - } - - /** @return Whether this location is really {@linkplain #NULL null}. */ - public boolean isNull() { - return address == 0; - } - - /** - * How many bytes is this location's address above a word-aligned address? - * - * @return The number of bytes offset. - */ - public int subWordAlignment() { - return address % WORD_SIZE; - } - - /** @return Whether this is a word-aligned location. */ - public boolean isAligned() { - return subWordAlignment() == 0; - } - - @Override - public int hashCode() { - return address; - } - - @Override - public boolean equals(Object other) { - return (other instanceof MemoryLocation o) && (o.address == address); - } - - @Override - public int compareTo(MemoryLocation other) { - return compareUnsigned(address, other.address); - } - - /** - * Test if this location is less than another location. - * - * @param other - * The other location. - * @return True if this location's address comes before. - */ - public boolean lessThan(MemoryLocation other) { - return compareTo(other) < 0; - } - - /** - * Test if this location is greater than another location. - * - * @param other - * The other location. - * @return True if this location's address comes after. - */ - public boolean greaterThan(MemoryLocation other) { - return compareTo(other) > 0; - } - - @Override - public String toString() { - // Leading '0x' then exactly 8 hexadecimal characters; 10 chars total - return format("%#010x", address); - } - - /** Maximum legal SpiNNaker address. It's a 32-bit machine. */ - private static final long MAX_ADDR = 0xFFFFFFFFL; - - /** - * Convert an address to a 32-bit integer. - * - * @param baseAddress - * The address as a long. - * @return the address as an int. - * @throws IllegalArgumentException - * if the value is outside the unsigned 32-bit integer range. - */ - private static int convert(long baseAddress) { - if (baseAddress < 0 || baseAddress > MAX_ADDR) { - throw new IllegalArgumentException( - "address must be in 32-bit unsigned integer range"); - } - return (int) baseAddress; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.Integer.compareUnsigned; +import static java.lang.String.format; + +import com.google.errorprone.annotations.Immutable; + +/** + * A location in SpiNNaker or BMP memory. Does not say which address space this + * is in. + * + * @author Donal Fellows + * @param address + * The actual location. + */ +@Immutable +public record MemoryLocation(int address) + implements Comparable { + /** Number of bytes in a SpiNNaker (ARM) word. */ + private static final int WORD_SIZE = 4; + + /** The zero memory location. Often means "no actual address". */ + public static final MemoryLocation NULL = new MemoryLocation(0); + + /** + * @param address + * The actual location. + */ + public MemoryLocation(long address) { + this(convert(address)); + } + + /** + * Add an offset to this location to get a new memory location. + * + * @param offset + * The offset to add. + * @return The new memory location. + */ + public MemoryLocation add(int offset) { + return new MemoryLocation(address + offset); + } + + /** + * Get the difference between this location and another. + * + * @param other + * The other location. + * @return This location's address minus the other location's address. + */ + public int diff(MemoryLocation other) { + return address - other.address; + } + + /** @return Whether this location is really {@linkplain #NULL null}. */ + public boolean isNull() { + return address == 0; + } + + /** + * How many bytes is this location's address above a word-aligned address? + * + * @return The number of bytes offset. + */ + public int subWordAlignment() { + return address % WORD_SIZE; + } + + /** @return Whether this is a word-aligned location. */ + public boolean isAligned() { + return subWordAlignment() == 0; + } + + @Override + public int hashCode() { + return address; + } + + @Override + public boolean equals(Object other) { + return (other instanceof MemoryLocation o) && (o.address == address); + } + + @Override + public int compareTo(MemoryLocation other) { + return compareUnsigned(address, other.address); + } + + /** + * Test if this location is less than another location. + * + * @param other + * The other location. + * @return True if this location's address comes before. + */ + public boolean lessThan(MemoryLocation other) { + return compareTo(other) < 0; + } + + /** + * Test if this location is greater than another location. + * + * @param other + * The other location. + * @return True if this location's address comes after. + */ + public boolean greaterThan(MemoryLocation other) { + return compareTo(other) > 0; + } + + @Override + public String toString() { + // Leading '0x' then exactly 8 hexadecimal characters; 10 chars total + return format("%#010x", address); + } + + /** Maximum legal SpiNNaker address. It's a 32-bit machine. */ + private static final long MAX_ADDR = 0xFFFFFFFFL; + + /** + * Convert an address to a 32-bit integer. + * + * @param baseAddress + * The address as a long. + * @return the address as an int. + * @throws IllegalArgumentException + * if the value is outside the unsigned 32-bit integer range. + */ + private static int convert(long baseAddress) { + if (baseAddress < 0 || baseAddress > MAX_ADDR) { + throw new IllegalArgumentException( + "address must be in 32-bit unsigned integer range"); + } + return (int) baseAddress; + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java index ed3aaef1a8..f02cf63de1 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineHeight.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_Y; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; - -/** - * Validates that a machine's height (in chips) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(MAX_Y + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidMachineHeight { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "machine height (${validatedValue}) " - + "must be at least 1 and no more than 256"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_Y; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.Positive; + +/** + * Validates that a machine's height (in chips) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(MAX_Y + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidMachineHeight { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "machine height (${validatedValue}) " + + "must be at least 1 and no more than 256"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java index 25564fb48c..b21d032811 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidMachineWidth.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_X; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; - -/** - * Validates that a machine's width (in chips) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(MAX_X + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidMachineWidth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "machine width (${validatedValue}) " - + "must be at least 1 and no more than 256"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.MachineDefaults.MAX_X; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.Positive; + +/** + * Validates that a machine's width (in chips) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(MAX_X + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidMachineWidth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "machine width (${validatedValue}) " + + "must be at least 1 and no more than 256"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java index 26b47ef0ea..71afdaf4c9 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidP.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip processor number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.PROCESSORS_PER_CHIP - 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidP { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "processor number (${validatedValue}) " - + "must be at least 0 and no more than 17"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip processor number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.PROCESSORS_PER_CHIP - 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidP { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "processor number (${validatedValue}) " + + "must be at least 0 and no more than 17"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java index 2f2b3d7725..9136ab5b35 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidX.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip X coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.MAX_X) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidX { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "X coordinate (${validatedValue}) " - + "must be at least 0 and no more than 255"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip X coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.MAX_X) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidX { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "X coordinate (${validatedValue}) " + + "must be at least 0 and no more than 255"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java index 6c8f52e762..ca7a2e03d3 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/ValidY.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a chip Y coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MachineDefaults.MAX_Y) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidY { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Y coordinate (${validatedValue}) " - + "must be at least 0 and no more than 255"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a chip Y coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MachineDefaults.MAX_Y) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidY { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Y coordinate (${validatedValue}) " + + "must be at least 0 and no more than 255"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java index 8dc4e9c25c..4c8eed8cea 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/BMPCoords.java @@ -1,151 +1,151 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.google.errorprone.annotations.Immutable; - -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * A simple description of a BMP to talk to. Supports equality and being used as - * a hash key. - *

- * Although every board technically has a BMP, they are managed at the level of - * a frame (when a sufficient quantity of boards is used, typically but not - * necessarily 24). Cabinets contain frames. - * - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"cabinet": 3, "frame": 2}
- * and can be deserialized from that, or: - *
{"c": 3, "f": 2}
- * It can also accept being deserialised from a JSON array, for a more compact - * notation: - *
[3, 2]
- * Finally, it can also be deserialised from the string form created by the - * {@link #toString()} method: - *
[c:3,f:2]
- * - * @author Donal Fellows - * @param cabinet - * The ID of the cabinet that contains the frame that contains the - * BMPs. - * @param frame - * The ID of the frame that contains the master BMP. Frames are - * contained within a cabinet. - */ -@Immutable -@JsonDeserialize(using = BMPCoords.Deserializer.class) -public record BMPCoords(@ValidCabinetNumber int cabinet, - @ValidFrameNumber int frame) implements Comparable { - /** Parses the result of {@link #toString()}. */ - private static final Pattern PATTERN = - Pattern.compile("^\\[c:(\\d+),f:(\\d+)\\]$"); - - /** - * Create an instance from its serial form. This is the form produced by - * {@link #toString()}. The serial form (where the numbers may vary) is: - * - *
-	 * [c:34,f:12]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @return The deserialised value. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public static BMPCoords parse(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException("bad argument: " + serialForm); - } - int idx = 0; - int cabinet = parseInt(m.group(++idx)); - int frame = parseInt(m.group(++idx)); - return new BMPCoords(cabinet, frame); - } - - @Override - public String toString() { - return "[c:" + cabinet + ",f:" + frame + "]"; - } - - @Override - public int compareTo(BMPCoords other) { - int cmp = compare(cabinet, other.cabinet); - if (cmp != 0) { - return cmp; - } - return compare(frame, other.frame); - } - - /** JSON deserializer for {@link BMPCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(BMPCoords.class); - } - - @Override - BMPCoords deserializeArray() throws IOException { - int c = getNextIntOfArray(); - int f = getNextIntOfArray(); - requireEndOfArray(); - return new BMPCoords(c, f); - } - - @Override - BMPCoords deserializeObject() throws IOException { - ValueHolder c = new ValueHolder<>(), - f = new ValueHolder<>(); - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "cabinet", "c" -> requireSetOnceInt(name, c); - case "frame", "f" -> requireSetOnceInt(name, f); - default -> unknownProperty(name); - } - } - if (c.isEmpty() || f.isEmpty()) { - missingProperty("c", c.getValue(), "f", f.getValue()); - } - return new BMPCoords(c.getValue(), f.getValue()); - } - - @Override - BMPCoords deserializeString(String string) { - return BMPCoords.parse(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("c", "f"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.errorprone.annotations.Immutable; + +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * A simple description of a BMP to talk to. Supports equality and being used as + * a hash key. + *

+ * Although every board technically has a BMP, they are managed at the level of + * a frame (when a sufficient quantity of boards is used, typically but not + * necessarily 24). Cabinets contain frames. + * + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"cabinet": 3, "frame": 2}
+ * and can be deserialized from that, or: + *
{"c": 3, "f": 2}
+ * It can also accept being deserialised from a JSON array, for a more compact + * notation: + *
[3, 2]
+ * Finally, it can also be deserialised from the string form created by the + * {@link #toString()} method: + *
[c:3,f:2]
+ * + * @author Donal Fellows + * @param cabinet + * The ID of the cabinet that contains the frame that contains the + * BMPs. + * @param frame + * The ID of the frame that contains the master BMP. Frames are + * contained within a cabinet. + */ +@Immutable +@JsonDeserialize(using = BMPCoords.Deserializer.class) +public record BMPCoords(@ValidCabinetNumber int cabinet, + @ValidFrameNumber int frame) implements Comparable { + /** Parses the result of {@link #toString()}. */ + private static final Pattern PATTERN = + Pattern.compile("^\\[c:(\\d+),f:(\\d+)\\]$"); + + /** + * Create an instance from its serial form. This is the form produced by + * {@link #toString()}. The serial form (where the numbers may vary) is: + * + *
+	 * [c:34,f:12]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @return The deserialised value. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public static BMPCoords parse(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException("bad argument: " + serialForm); + } + int idx = 0; + int cabinet = parseInt(m.group(++idx)); + int frame = parseInt(m.group(++idx)); + return new BMPCoords(cabinet, frame); + } + + @Override + public String toString() { + return "[c:" + cabinet + ",f:" + frame + "]"; + } + + @Override + public int compareTo(BMPCoords other) { + int cmp = compare(cabinet, other.cabinet); + if (cmp != 0) { + return cmp; + } + return compare(frame, other.frame); + } + + /** JSON deserializer for {@link BMPCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(BMPCoords.class); + } + + @Override + BMPCoords deserializeArray() throws IOException { + int c = getNextIntOfArray(); + int f = getNextIntOfArray(); + requireEndOfArray(); + return new BMPCoords(c, f); + } + + @Override + BMPCoords deserializeObject() throws IOException { + ValueHolder c = new ValueHolder<>(), + f = new ValueHolder<>(); + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "cabinet", "c" -> requireSetOnceInt(name, c); + case "frame", "f" -> requireSetOnceInt(name, f); + default -> unknownProperty(name); + } + } + if (c.isEmpty() || f.isEmpty()) { + missingProperty("c", c.getValue(), "f", f.getValue()); + } + return new BMPCoords(c.getValue(), f.getValue()); + } + + @Override + BMPCoords deserializeString(String string) { + return BMPCoords.parse(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("c", "f"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java index d1b3b225ae..c50f659e94 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/DeserializerHelper.java @@ -1,211 +1,211 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationConfig; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import com.google.errorprone.annotations.ForOverride; -import com.google.errorprone.annotations.FormatMethod; - -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * A helper class for JSON deserializers. - * - * @param - * The type of values the deserializer deserializes. - */ -@SuppressWarnings("serial") -abstract class DeserializerHelper extends StdDeserializer { - private static final ThreadLocal CONTEXT = - new ThreadLocal<>(); - - private static final ThreadLocal PARSER = new ThreadLocal<>(); - - protected DeserializerHelper(Class cls) { - super(cls); - } - - @Override - public final T deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException { - try { - CONTEXT.set(ctxt); - PARSER.set(p); - return switch (p.currentToken()) { - case START_ARRAY -> deserializeArray(); - case START_OBJECT -> deserializeObject(); - case VALUE_STRING -> deserializeString(p.getValueAsString()); - default -> { - ctxt.handleUnexpectedToken(_valueClass, p); - yield null; - } - }; - } finally { - CONTEXT.remove(); - PARSER.remove(); - } - } - - /** - * Deserialize an array to an instance. - * - * @return The instance - * @throws IOException - * On failure - */ - @ForOverride - abstract T deserializeArray() throws IOException; - - /** - * Deserialize an object to an instance. - * - * @return The instance - * @throws IOException - * On failure - */ - @ForOverride - abstract T deserializeObject() throws IOException; - - /** - * Deserialize a string to an instance. - * - * @param string - * The string, already extracted. - * @return The instance - * @throws IllegalArgumentException - * On failure - */ - @ForOverride - abstract T deserializeString(String string); - - /** - * Throw an exception because of an unexpected token. - * - * @param cls - * What we were trying to instantiate. - * @throws IOException - * The exception always thrown. - */ - private void unexpectedToken(Class cls) throws IOException { - CONTEXT.get().handleUnexpectedToken(cls, PARSER.get()); - } - - /** - * Throw an exception because of an input mismatch. - * - * @param msg - * Used to describe the problem. - * @param args - * Values to substitute in. - * @throws IOException - * The exception always thrown. - */ - @FormatMethod - private void inputMismatch(String msg, Object... args) - throws IOException { - CONTEXT.get().reportInputMismatch(_valueClass, msg, args); - } - - /** - * Throw an exception because of an unknown property. - * - * @param name - * The unknown property name. - * @throws IOException - * The exception always thrown. - */ - void unknownProperty(String name) throws IOException { - CONTEXT.get().handleUnknownProperty(PARSER.get(), this, _valueClass, - name); - } - - int getNextIntOfArray() throws IOException { - var p = PARSER.get(); - if (!p.nextToken().isNumeric()) { - unexpectedToken(int.class); - } - return p.getIntValue(); - } - - String getNextFieldName() throws IOException { - var p = PARSER.get(); - var name = p.nextFieldName(); - if (name == null) { - if (!p.currentToken().isStructEnd()) { - unexpectedToken(_valueClass); - } - } - return name; - } - - void requireEndOfArray() throws IOException { - var p = PARSER.get(); - if (!p.nextToken().isStructEnd()) { - unexpectedToken(_valueClass); - } - } - - int requireSetOnceInt(String name, Integer current) throws IOException { - if (current != null) { - inputMismatch("Duplicate property '%s'", name); - } - return PARSER.get().nextIntValue(0); - } - - void requireSetOnceInt(String name, ValueHolder holder) - throws IOException { - if (!holder.isEmpty()) { - inputMismatch("Duplicate property '%s'", name); - } - holder.setValue(PARSER.get().nextIntValue(0)); - } - - void missingProperty(String n1, Object v1) throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } - } - - void missingProperty(String n1, Object v1, String n2, Object v2) - throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } else if (v2 == null) { - inputMismatch("Missing required property '%s'", n2); - } - } - - void missingProperty(String n1, Object v1, String n2, Object v2, String n3, - Object v3) throws IOException { - if (v1 == null) { - inputMismatch("Missing required property '%s'", n1); - } else if (v2 == null) { - inputMismatch("Missing required property '%s'", n2); - } else if (v3 == null) { - inputMismatch("Missing required property '%s'", n3); - } - } - - @Override - public final Boolean supportsUpdate(DeserializationConfig config) { - return Boolean.FALSE; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.google.errorprone.annotations.ForOverride; +import com.google.errorprone.annotations.FormatMethod; + +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * A helper class for JSON deserializers. + * + * @param + * The type of values the deserializer deserializes. + */ +@SuppressWarnings("serial") +abstract class DeserializerHelper extends StdDeserializer { + private static final ThreadLocal CONTEXT = + new ThreadLocal<>(); + + private static final ThreadLocal PARSER = new ThreadLocal<>(); + + protected DeserializerHelper(Class cls) { + super(cls); + } + + @Override + public final T deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException { + try { + CONTEXT.set(ctxt); + PARSER.set(p); + return switch (p.currentToken()) { + case START_ARRAY -> deserializeArray(); + case START_OBJECT -> deserializeObject(); + case VALUE_STRING -> deserializeString(p.getValueAsString()); + default -> { + ctxt.handleUnexpectedToken(_valueClass, p); + yield null; + } + }; + } finally { + CONTEXT.remove(); + PARSER.remove(); + } + } + + /** + * Deserialize an array to an instance. + * + * @return The instance + * @throws IOException + * On failure + */ + @ForOverride + abstract T deserializeArray() throws IOException; + + /** + * Deserialize an object to an instance. + * + * @return The instance + * @throws IOException + * On failure + */ + @ForOverride + abstract T deserializeObject() throws IOException; + + /** + * Deserialize a string to an instance. + * + * @param string + * The string, already extracted. + * @return The instance + * @throws IllegalArgumentException + * On failure + */ + @ForOverride + abstract T deserializeString(String string); + + /** + * Throw an exception because of an unexpected token. + * + * @param cls + * What we were trying to instantiate. + * @throws IOException + * The exception always thrown. + */ + private void unexpectedToken(Class cls) throws IOException { + CONTEXT.get().handleUnexpectedToken(cls, PARSER.get()); + } + + /** + * Throw an exception because of an input mismatch. + * + * @param msg + * Used to describe the problem. + * @param args + * Values to substitute in. + * @throws IOException + * The exception always thrown. + */ + @FormatMethod + private void inputMismatch(String msg, Object... args) + throws IOException { + CONTEXT.get().reportInputMismatch(_valueClass, msg, args); + } + + /** + * Throw an exception because of an unknown property. + * + * @param name + * The unknown property name. + * @throws IOException + * The exception always thrown. + */ + void unknownProperty(String name) throws IOException { + CONTEXT.get().handleUnknownProperty(PARSER.get(), this, _valueClass, + name); + } + + int getNextIntOfArray() throws IOException { + var p = PARSER.get(); + if (!p.nextToken().isNumeric()) { + unexpectedToken(int.class); + } + return p.getIntValue(); + } + + String getNextFieldName() throws IOException { + var p = PARSER.get(); + var name = p.nextFieldName(); + if (name == null) { + if (!p.currentToken().isStructEnd()) { + unexpectedToken(_valueClass); + } + } + return name; + } + + void requireEndOfArray() throws IOException { + var p = PARSER.get(); + if (!p.nextToken().isStructEnd()) { + unexpectedToken(_valueClass); + } + } + + int requireSetOnceInt(String name, Integer current) throws IOException { + if (current != null) { + inputMismatch("Duplicate property '%s'", name); + } + return PARSER.get().nextIntValue(0); + } + + void requireSetOnceInt(String name, ValueHolder holder) + throws IOException { + if (!holder.isEmpty()) { + inputMismatch("Duplicate property '%s'", name); + } + holder.setValue(PARSER.get().nextIntValue(0)); + } + + void missingProperty(String n1, Object v1) throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } + } + + void missingProperty(String n1, Object v1, String n2, Object v2) + throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } else if (v2 == null) { + inputMismatch("Missing required property '%s'", n2); + } + } + + void missingProperty(String n1, Object v1, String n2, Object v2, String n3, + Object v3) throws IOException { + if (v1 == null) { + inputMismatch("Missing required property '%s'", n1); + } else if (v2 == null) { + inputMismatch("Missing required property '%s'", n2); + } else if (v3 == null) { + inputMismatch("Missing required property '%s'", n3); + } + } + + @Override + public final Boolean supportsUpdate(DeserializationConfig config) { + return Boolean.FALSE; + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java index 81887c239f..e349adbe66 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/Limits.java @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -/** - * Various limits. These are constrained by the requirement that each of the - * dimensions of the coordinates for a chip fit in an unsigned byte. - */ -interface Limits { - /** - * Max triad X coordinate. Any larger and the chips become unaddressible. - */ - int MAX_TRIAD_X = 20; - - /** - * Max triad Y coordinate. Any larger and the chips become unaddressible. - */ - int MAX_TRIAD_Y = 20; - - /** Max triad Z coordinate. */ - int MAX_TRIAD_Z = 2; - - /** - * Maximum cabinet number. Any larger than this will result in the - * underlying chips becoming unaddressible. - */ - int MAX_CABINET = 31; - - /** - * Maximum frame number. Any larger than this will result in the underlying - * chips becoming unaddressible. - */ - int MAX_FRAME = 31; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +/** + * Various limits. These are constrained by the requirement that each of the + * dimensions of the coordinates for a chip fit in an unsigned byte. + */ +interface Limits { + /** + * Max triad X coordinate. Any larger and the chips become unaddressible. + */ + int MAX_TRIAD_X = 20; + + /** + * Max triad Y coordinate. Any larger and the chips become unaddressible. + */ + int MAX_TRIAD_Y = 20; + + /** Max triad Z coordinate. */ + int MAX_TRIAD_Z = 2; + + /** + * Maximum cabinet number. Any larger than this will result in the + * underlying chips becoming unaddressible. + */ + int MAX_CABINET = 31; + + /** + * Maximum frame number. Any larger than this will result in the underlying + * chips becoming unaddressible. + */ + int MAX_FRAME = 31; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java index 5d2d88cf8e..04e8f89426 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/PhysicalCoords.java @@ -1,170 +1,170 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.google.errorprone.annotations.Immutable; - -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * Physical board coordinates. The {@code cabinet} and {@code frame} (with - * multiple frames per cabinet) describe where a board is located within the - * physical layout of the machine (and also which BMP is managing it, as there - * is one managing BMP per frame). The {@code board} number says which board - * within the frame is being referred to. - * - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"cabinet": 3, "frame": 2, "board": 1}
- * and can be deserialized from that, or: - *
{"c": 3, "f": 2, "b": 1}
- * It can also accept being deserialised from a JSON array, for a more compact - * notation: - *
[3, 2, 1]
- * Finally, it can also be deserialised from the string form created by the - * {@link #toString()} method: - *
[c:3,f:2,b:1]
- * - * @author Donal Fellows - * @param c - * Cabinet number. - * @param f - * Frame number. - * @param b - * Board number. - */ -@Immutable -@JsonDeserialize(using = PhysicalCoords.Deserializer.class) -public record PhysicalCoords(// - @JsonProperty("c") @ValidCabinetNumber int c, - @JsonProperty("f") @ValidFrameNumber int f, - @JsonProperty("b") @ValidBoardNumber int b) - implements Comparable { - private static final Pattern PATTERN = - Pattern.compile("^\\[c:(\\d+),f:(\\d+),b:(\\d+)\\]$"); - - /** - * Create an instance from its serial form. The serial form (where the - * numbers may vary) is: - * - *
-	 * [c:34,f:12,b:23]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @return The deserialised value. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public static PhysicalCoords parse(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException("bad argument: " + serialForm); - } - int idx = 0; - int c = parseInt(m.group(++idx)); - int f = parseInt(m.group(++idx)); - int b = parseInt(m.group(++idx)); - return new PhysicalCoords(c, f, b); - } - - @Override - public String toString() { - return "[c:" + c + ",f:" + f + ",b:" + b + "]"; - } - - /** - * @return The coordinates of the BMP that manages this board. - */ - @JsonIgnore - public BMPCoords getBmpCoords() { - return new BMPCoords(c, f); - } - - @Override - public int compareTo(PhysicalCoords other) { - int cmp = compare(c, other.c); - if (cmp != 0) { - return cmp; - } - cmp = compare(f, other.f); - if (cmp != 0) { - return cmp; - } - return compare(b, other.b); - } - - /** JSON deserializer for {@link PhysicalCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(PhysicalCoords.class); - } - - @Override - PhysicalCoords deserializeArray() throws IOException { - int c = getNextIntOfArray(); - int f = getNextIntOfArray(); - int b = getNextIntOfArray(); - requireEndOfArray(); - return new PhysicalCoords(c, f, b); - } - - @Override - PhysicalCoords deserializeObject() throws IOException { - ValueHolder c = new ValueHolder<>(), - f = new ValueHolder<>(), b = new ValueHolder<>(); - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "cabinet", "c" -> requireSetOnceInt(name, c); - case "frame", "f" -> requireSetOnceInt(name, f); - case "board", "b" -> requireSetOnceInt(name, b); - default -> unknownProperty(name); - } - } - if (c.isEmpty() || f.isEmpty() || b.isEmpty()) { - missingProperty("c", c.getValue(), "f", f.getValue(), "b", - b.getValue()); - } - return new PhysicalCoords(c.getValue(), f.getValue(), b.getValue()); - } - - @Override - PhysicalCoords deserializeString(String string) { - return PhysicalCoords.parse(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("c", "f", "b"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.errorprone.annotations.Immutable; + +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * Physical board coordinates. The {@code cabinet} and {@code frame} (with + * multiple frames per cabinet) describe where a board is located within the + * physical layout of the machine (and also which BMP is managing it, as there + * is one managing BMP per frame). The {@code board} number says which board + * within the frame is being referred to. + * + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"cabinet": 3, "frame": 2, "board": 1}
+ * and can be deserialized from that, or: + *
{"c": 3, "f": 2, "b": 1}
+ * It can also accept being deserialised from a JSON array, for a more compact + * notation: + *
[3, 2, 1]
+ * Finally, it can also be deserialised from the string form created by the + * {@link #toString()} method: + *
[c:3,f:2,b:1]
+ * + * @author Donal Fellows + * @param c + * Cabinet number. + * @param f + * Frame number. + * @param b + * Board number. + */ +@Immutable +@JsonDeserialize(using = PhysicalCoords.Deserializer.class) +public record PhysicalCoords(// + @JsonProperty("c") @ValidCabinetNumber int c, + @JsonProperty("f") @ValidFrameNumber int f, + @JsonProperty("b") @ValidBoardNumber int b) + implements Comparable { + private static final Pattern PATTERN = + Pattern.compile("^\\[c:(\\d+),f:(\\d+),b:(\\d+)\\]$"); + + /** + * Create an instance from its serial form. The serial form (where the + * numbers may vary) is: + * + *
+	 * [c:34,f:12,b:23]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @return The deserialised value. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public static PhysicalCoords parse(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException("bad argument: " + serialForm); + } + int idx = 0; + int c = parseInt(m.group(++idx)); + int f = parseInt(m.group(++idx)); + int b = parseInt(m.group(++idx)); + return new PhysicalCoords(c, f, b); + } + + @Override + public String toString() { + return "[c:" + c + ",f:" + f + ",b:" + b + "]"; + } + + /** + * @return The coordinates of the BMP that manages this board. + */ + @JsonIgnore + public BMPCoords getBmpCoords() { + return new BMPCoords(c, f); + } + + @Override + public int compareTo(PhysicalCoords other) { + int cmp = compare(c, other.c); + if (cmp != 0) { + return cmp; + } + cmp = compare(f, other.f); + if (cmp != 0) { + return cmp; + } + return compare(b, other.b); + } + + /** JSON deserializer for {@link PhysicalCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(PhysicalCoords.class); + } + + @Override + PhysicalCoords deserializeArray() throws IOException { + int c = getNextIntOfArray(); + int f = getNextIntOfArray(); + int b = getNextIntOfArray(); + requireEndOfArray(); + return new PhysicalCoords(c, f, b); + } + + @Override + PhysicalCoords deserializeObject() throws IOException { + ValueHolder c = new ValueHolder<>(), + f = new ValueHolder<>(), b = new ValueHolder<>(); + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "cabinet", "c" -> requireSetOnceInt(name, c); + case "frame", "f" -> requireSetOnceInt(name, f); + case "board", "b" -> requireSetOnceInt(name, b); + default -> unknownProperty(name); + } + } + if (c.isEmpty() || f.isEmpty() || b.isEmpty()) { + missingProperty("c", c.getValue(), "f", f.getValue(), "b", + b.getValue()); + } + return new PhysicalCoords(c.getValue(), f.getValue(), b.getValue()); + } + + @Override + PhysicalCoords deserializeString(String string) { + return PhysicalCoords.parse(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("c", "f", "b"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java index fd483a588c..81b7aa44e9 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/TriadCoords.java @@ -1,193 +1,193 @@ -/* - * Copyright (c) 2021-2022 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 - * - * http://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.machine.board; - -import static java.lang.Integer.compare; -import static java.lang.Integer.parseInt; - -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - -import uk.ac.manchester.spinnaker.machine.ChipLocation; -import uk.ac.manchester.spinnaker.utils.ValueHolder; - -/** - * Triad coordinates. - * Boards are in groups of three (triads) that group together in a rectangular - * grid. The {@code x} and {@code y} coordinates say which group of three in the - * grid, and the {@code z} coordinate says which board within the group. The - * group is not itself rectangular, but tesselates on a rectangular grid. - *

- * To understand how the triad coordinate system works, consider this board - * layout (a classic 24 board machine, with wrap-arounds not shown): - *

- * 24-board layout - *

Serialisation Formats

- * Defaults to being serialised as a JSON object: - *
{"x": 3, "y": 2, "z": 1}
- * and can also be deserialized from that, but can also accept being - * deserialised from a JSON array: - *
[3, 2, 1]
- * and can also be deserialized from its {@linkplain #toString() string form}: - *
[x:3,y:2,z:1]
- * - * @author Donal Fellows - * @param x - * X coordinate of triad. - * @param y - * Y coordinate of triad. - * @param z - * Z coordinate of triad. - */ -@JsonDeserialize(using = TriadCoords.Deserializer.class) -public record TriadCoords(// - @JsonProperty("x") @ValidTriadX int x, - @JsonProperty("y") @ValidTriadY int y, - @JsonProperty("z") @ValidTriadZ int z) - implements Comparable { - /** The width and height of a triad, in chips. */ - private static final int TRIAD_CHIP_SIZE = 12; - - private static final int TRIAD_MAJOR_OFFSET = 8; - - private static final int TRIAD_MINOR_OFFSET = 4; - - /** Parses the string produced by {@link #toString()}. */ - private static final Pattern PATTERN = - Pattern.compile("^\\[x:(\\d+),y:(\\d+),z:(\\d+)\\]$"); - - /** - * Create an instance from its serial form. The serial form (where the - * numbers may vary) is: - * - *
-	 * [x:3,y:5,z:2]
-	 * 
- * - * @param serialForm - * The form to deserialise. - * @return The deserialised value. - * @throws IllegalArgumentException - * If the string is not in the right form. - */ - @JsonCreator - public static TriadCoords parse(String serialForm) { - var m = PATTERN.matcher(serialForm); - if (!m.matches()) { - throw new IllegalArgumentException( - "bad argument: " + serialForm); - } - int idx = 0; - int x = parseInt(m.group(++idx)); - int y = parseInt(m.group(++idx)); - int z = parseInt(m.group(++idx)); - return new TriadCoords(x, y, z); - } - - /** - * Convert these coordinates into a machine-global chip location. - * - * @return The chip location relative to the root of the machine. - */ - public ChipLocation asChipLocation() { - int rootX = x * TRIAD_CHIP_SIZE; - int rootY = y * TRIAD_CHIP_SIZE; - switch (z) { - case 1 -> { - rootX += TRIAD_MAJOR_OFFSET; - rootY += TRIAD_MINOR_OFFSET; - } - case 2 -> { - rootX += TRIAD_MINOR_OFFSET; - rootY += TRIAD_MAJOR_OFFSET; - } - default -> { - } - } - return new ChipLocation(rootX, rootY); - } - - @Override - public String toString() { - return "[x:" + x + ",y:" + y + ",z:" + z + "]"; - } - - @Override - public int compareTo(TriadCoords other) { - int cmp = compare(x, other.x); - if (cmp != 0) { - return cmp; - } - cmp = compare(y, other.y); - if (cmp != 0) { - return cmp; - } - return compare(z, other.z); - } - - /** JSON deserializer for {@link TriadCoords}. */ - static final class Deserializer extends DeserializerHelper { - private static final long serialVersionUID = 1L; - - Deserializer() { - super(TriadCoords.class); - } - - @Override - TriadCoords deserializeArray() throws IOException { - int x = getNextIntOfArray(); - int y = getNextIntOfArray(); - int z = getNextIntOfArray(); - requireEndOfArray(); - return new TriadCoords(x, y, z); - } - - @Override - TriadCoords deserializeObject() throws IOException { - ValueHolder x = new ValueHolder<>(), - y = new ValueHolder<>(), z = new ValueHolder<>(); - String name; - while ((name = getNextFieldName()) != null) { - switch (name) { - case "x" -> requireSetOnceInt(name, x); - case "y" -> requireSetOnceInt(name, y); - case "z" -> requireSetOnceInt(name, z); - default -> unknownProperty(name); - } - } - if (x.isEmpty() || y.isEmpty() || z.isEmpty()) { - missingProperty("x", x.getValue(), "y", y.getValue(), "z", - z.getValue()); - } - return new TriadCoords(x.getValue(), y.getValue(), z.getValue()); - } - - @Override - TriadCoords deserializeString(String string) { - return TriadCoords.parse(string); - } - - @Override - public List getKnownPropertyNames() { - return List.of("x", "y", "z"); - } - } -} +/* + * Copyright (c) 2021-2022 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 + * + * http://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.machine.board; + +import static java.lang.Integer.compare; +import static java.lang.Integer.parseInt; + +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import uk.ac.manchester.spinnaker.machine.ChipLocation; +import uk.ac.manchester.spinnaker.utils.ValueHolder; + +/** + * Triad coordinates. + * Boards are in groups of three (triads) that group together in a rectangular + * grid. The {@code x} and {@code y} coordinates say which group of three in the + * grid, and the {@code z} coordinate says which board within the group. The + * group is not itself rectangular, but tesselates on a rectangular grid. + *

+ * To understand how the triad coordinate system works, consider this board + * layout (a classic 24 board machine, with wrap-arounds not shown): + *

+ * 24-board layout + *

Serialisation Formats

+ * Defaults to being serialised as a JSON object: + *
{"x": 3, "y": 2, "z": 1}
+ * and can also be deserialized from that, but can also accept being + * deserialised from a JSON array: + *
[3, 2, 1]
+ * and can also be deserialized from its {@linkplain #toString() string form}: + *
[x:3,y:2,z:1]
+ * + * @author Donal Fellows + * @param x + * X coordinate of triad. + * @param y + * Y coordinate of triad. + * @param z + * Z coordinate of triad. + */ +@JsonDeserialize(using = TriadCoords.Deserializer.class) +public record TriadCoords(// + @JsonProperty("x") @ValidTriadX int x, + @JsonProperty("y") @ValidTriadY int y, + @JsonProperty("z") @ValidTriadZ int z) + implements Comparable { + /** The width and height of a triad, in chips. */ + private static final int TRIAD_CHIP_SIZE = 12; + + private static final int TRIAD_MAJOR_OFFSET = 8; + + private static final int TRIAD_MINOR_OFFSET = 4; + + /** Parses the string produced by {@link #toString()}. */ + private static final Pattern PATTERN = + Pattern.compile("^\\[x:(\\d+),y:(\\d+),z:(\\d+)\\]$"); + + /** + * Create an instance from its serial form. The serial form (where the + * numbers may vary) is: + * + *
+	 * [x:3,y:5,z:2]
+	 * 
+ * + * @param serialForm + * The form to deserialise. + * @return The deserialised value. + * @throws IllegalArgumentException + * If the string is not in the right form. + */ + @JsonCreator + public static TriadCoords parse(String serialForm) { + var m = PATTERN.matcher(serialForm); + if (!m.matches()) { + throw new IllegalArgumentException( + "bad argument: " + serialForm); + } + int idx = 0; + int x = parseInt(m.group(++idx)); + int y = parseInt(m.group(++idx)); + int z = parseInt(m.group(++idx)); + return new TriadCoords(x, y, z); + } + + /** + * Convert these coordinates into a machine-global chip location. + * + * @return The chip location relative to the root of the machine. + */ + public ChipLocation asChipLocation() { + int rootX = x * TRIAD_CHIP_SIZE; + int rootY = y * TRIAD_CHIP_SIZE; + switch (z) { + case 1 -> { + rootX += TRIAD_MAJOR_OFFSET; + rootY += TRIAD_MINOR_OFFSET; + } + case 2 -> { + rootX += TRIAD_MINOR_OFFSET; + rootY += TRIAD_MAJOR_OFFSET; + } + default -> { + } + } + return new ChipLocation(rootX, rootY); + } + + @Override + public String toString() { + return "[x:" + x + ",y:" + y + ",z:" + z + "]"; + } + + @Override + public int compareTo(TriadCoords other) { + int cmp = compare(x, other.x); + if (cmp != 0) { + return cmp; + } + cmp = compare(y, other.y); + if (cmp != 0) { + return cmp; + } + return compare(z, other.z); + } + + /** JSON deserializer for {@link TriadCoords}. */ + static final class Deserializer extends DeserializerHelper { + private static final long serialVersionUID = 1L; + + Deserializer() { + super(TriadCoords.class); + } + + @Override + TriadCoords deserializeArray() throws IOException { + int x = getNextIntOfArray(); + int y = getNextIntOfArray(); + int z = getNextIntOfArray(); + requireEndOfArray(); + return new TriadCoords(x, y, z); + } + + @Override + TriadCoords deserializeObject() throws IOException { + ValueHolder x = new ValueHolder<>(), + y = new ValueHolder<>(), z = new ValueHolder<>(); + String name; + while ((name = getNextFieldName()) != null) { + switch (name) { + case "x" -> requireSetOnceInt(name, x); + case "y" -> requireSetOnceInt(name, y); + case "z" -> requireSetOnceInt(name, z); + default -> unknownProperty(name); + } + } + if (x.isEmpty() || y.isEmpty() || z.isEmpty()) { + missingProperty("x", x.getValue(), "y", y.getValue(), "z", + z.getValue()); + } + return new TriadCoords(x.getValue(), y.getValue(), z.getValue()); + } + + @Override + TriadCoords deserializeString(String string) { + return TriadCoords.parse(string); + } + + @Override + public List getKnownPropertyNames() { + return List.of("x", "y", "z"); + } + } +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java index 60123239db..3ebad3c71e 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidBoardNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.BMPBoard.MAX_BOARD_NUMBER; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a board number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_BOARD_NUMBER) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidBoardNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "board number (${validatedValue}) " - + "must be in range 0-23"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.BMPBoard.MAX_BOARD_NUMBER; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a board number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_BOARD_NUMBER) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidBoardNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "board number (${validatedValue}) " + + "must be in range 0-23"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java index ec224dcae3..2f7867e741 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidCabinetNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_CABINET; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a cabinet number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_CABINET) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidCabinetNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "cabinet number (${validatedValue}) " - + "must be in range 0-31"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_CABINET; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a cabinet number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_CABINET) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidCabinetNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "cabinet number (${validatedValue}) " + + "must be in range 0-31"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java index dfaaa42f21..a40170ea21 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidFrameNumber.java @@ -1,69 +1,69 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_FRAME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a frame number is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(MAX_FRAME) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidFrameNumber { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "frame number (${validatedValue}) " - + "must be in range 0-31"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static uk.ac.manchester.spinnaker.machine.board.Limits.MAX_FRAME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a frame number is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(MAX_FRAME) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidFrameNumber { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "frame number (${validatedValue}) " + + "must be in range 0-31"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java index cfb709da5d..9851bd81ab 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadDepth.java @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; - -/** - * Validates that a machine's depth is in a sane range. Note that only machines - * with a single board typically have a depth other than 3, and the current - * implementation never uses a depth of 2. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_Z + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadDepth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad depth (${validatedValue}) " - + "must be at least 1 and no more than 3"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.Positive; + +/** + * Validates that a machine's depth is in a sane range. Note that only machines + * with a single board typically have a depth other than 3, and the current + * implementation never uses a depth of 2. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_Z + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadDepth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad depth (${validatedValue}) " + + "must be at least 1 and no more than 3"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java index f43ab46d45..dc29ab3367 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadHeight.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; - -/** - * Validates that a machine's height (in triads) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_Y + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadHeight { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad height (${validatedValue}) " - + "must be at least 1 and no more than 21"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.Positive; + +/** + * Validates that a machine's height (in triads) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_Y + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadHeight { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad height (${validatedValue}) " + + "must be at least 1 and no more than 21"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java index cf1d897e2e..afffd0cccc 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadWidth.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.Positive; - -/** - * Validates that a machine's width (in triads) is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Positive -@Max(Limits.MAX_TRIAD_X + 1) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadWidth { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "triad width (${validatedValue}) " - + "must be at least 1 and no more than 21"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.Positive; + +/** + * Validates that a machine's width (in triads) is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Positive +@Max(Limits.MAX_TRIAD_X + 1) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadWidth { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "triad width (${validatedValue}) " + + "must be at least 1 and no more than 21"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java index 5f36e1c52f..3de1bee4c4 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadX.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad X coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_X) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadX { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "X coordinate (${validatedValue}) " - + "must be at least 0 and no more than 63"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad X coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_X) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadX { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "X coordinate (${validatedValue}) " + + "must be at least 0 and no more than 63"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java index 95a4739aa3..86b6ae2d08 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadY.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad Y coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_Y) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadY { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Y coordinate (${validatedValue}) " - + "must be at least 0 and no more than 63"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad Y coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_Y) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadY { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Y coordinate (${validatedValue}) " + + "must be at least 0 and no more than 63"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java index 933072cd15..8ed94c0eb3 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/ValidTriadZ.java @@ -1,68 +1,68 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.machine.board; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.ReportAsSingleViolation; -import javax.validation.constraints.Max; -import javax.validation.constraints.PositiveOrZero; - -/** - * Validates that a triad Z coordinate is in a sane range. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@PositiveOrZero -@Max(Limits.MAX_TRIAD_Z) -@Constraint(validatedBy = {}) -@ReportAsSingleViolation -public @interface ValidTriadZ { - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "Z coordinate (${validatedValue}) " - + "must be 0, 1, or 2"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} +/* + * Copyright (c) 2022 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 + * + * http://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.machine.board; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.constraints.Max; +import javax.validation.constraints.PositiveOrZero; + +/** + * Validates that a triad Z coordinate is in a sane range. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@PositiveOrZero +@Max(Limits.MAX_TRIAD_Z) +@Constraint(validatedBy = {}) +@ReportAsSingleViolation +public @interface ValidTriadZ { + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "Z coordinate (${validatedValue}) " + + "must be 0, 1, or 2"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java index a299c226ce..2927f79bbb 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/board/package-info.java @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2022 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 - * - * http://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. - */ -/** - * Classes relating to boards in a SpiNNaker machine. Note that boards - * themselves mostly not modelled, but their coordinates schemes are because - * they are used in many places. - */ -package uk.ac.manchester.spinnaker.machine.board; +/* + * Copyright (c) 2022 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 + * + * http://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. + */ +/** + * Classes relating to boards in a SpiNNaker machine. Note that boards + * themselves mostly not modelled, but their coordinates schemes are because + * they are used in many places. + */ +package uk.ac.manchester.spinnaker.machine.board; diff --git a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java index 333473634c..f13c9ecdc3 100644 --- a/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java +++ b/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/tags/TagID.java @@ -1,103 +1,103 @@ -/* - * 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 - * - * http://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.machine.tags; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -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; - -/** - * Validates that a number looks like a tag identifier. Always accepts - * {@code null}. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = TagIDValidator.class) -public @interface TagID { - /** - * Whether to allow the SC&MP-dedicated tag. - * - * @return Whether 0 is allowed. - */ - boolean scamp() default false; - - /** - * Whether to also allow ephemeral tags. - * - * @return Whether 8-15 are allowed - */ - boolean ephemeral() default false; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad tag identifier"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; -} - -class TagIDValidator implements ConstraintValidator { - private static final int MAX_TAG = 7; - - private static final int MAX_EPHEMERAL = 15; - - private int min; - - private int max; - - @Override - public void initialize(TagID annotation) { - min = annotation.scamp() ? 0 : 1; - max = annotation.ephemeral() ? MAX_EPHEMERAL : MAX_TAG; - } - - @Override - public boolean isValid(Integer value, ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - return (value >= min) && (value <= max); - } -} +/* + * 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 + * + * http://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.machine.tags; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +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; + +/** + * Validates that a number looks like a tag identifier. Always accepts + * {@code null}. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = TagIDValidator.class) +public @interface TagID { + /** + * Whether to allow the SC&MP-dedicated tag. + * + * @return Whether 0 is allowed. + */ + boolean scamp() default false; + + /** + * Whether to also allow ephemeral tags. + * + * @return Whether 8-15 are allowed + */ + boolean ephemeral() default false; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad tag identifier"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; +} + +class TagIDValidator implements ConstraintValidator { + private static final int MAX_TAG = 7; + + private static final int MAX_EPHEMERAL = 15; + + private int min; + + private int max; + + @Override + public void initialize(TagID annotation) { + min = annotation.scamp() ? 0 : 1; + max = annotation.ephemeral() ? MAX_EPHEMERAL : MAX_TAG; + } + + @Override + public boolean isValid(Integer value, ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + return (value >= min) && (value <= max); + } +} diff --git a/SpiNNaker-machine/src/test/resources/h40w16.json b/SpiNNaker-machine/src/test/resources/h40w16.json index d70130e002..0d66f329d1 100644 --- a/SpiNNaker-machine/src/test/resources/h40w16.json +++ b/SpiNNaker-machine/src/test/resources/h40w16.json @@ -1 +1 @@ -{"height": 40, "width": 16, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "10.11.197.9"}], [0, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [0, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.25"}], [0, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3, 4]}], [0, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.9"}], [0, 25, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 26, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 27, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [1, 4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0]}], [1, 2, {"cores": 17, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [1, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [1, 13, {"cores": 17, "ethernet": [0, 12]}], [1, 14, {"cores": 17, "ethernet": [0, 12]}], [1, 15, {"cores": 17, "ethernet": [0, 12]}], [1, 16, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [1, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [1, 25, {"cores": 17, "ethernet": [0, 24]}], [1, 26, {"cores": 17, "ethernet": [0, 24]}], [1, 27, {"cores": 17, "ethernet": [0, 24]}], [1, 28, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [2, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 4, 5]}], [2, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [5]}], [2, 3, {"cores": 17, "ethernet": [0, 0]}], [2, 4, {"cores": 17, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [2, 13, {"cores": 17, "ethernet": [0, 12]}], [2, 14, {"cores": 17, "ethernet": [0, 12]}], [2, 15, {"cores": 17, "ethernet": [0, 12]}], [2, 16, {"cores": 17, "ethernet": [0, 12]}], [2, 17, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [2, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [2, 25, {"cores": 17, "ethernet": [0, 24]}], [2, 26, {"cores": 17, "ethernet": [0, 24]}], [2, 27, {"cores": 17, "ethernet": [0, 24]}], [2, 28, {"cores": 17, "ethernet": [0, 24]}], [2, 29, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [3, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [3, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4]}], [3, 3, {"cores": 16, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [3, 13, {"cores": 17, "ethernet": [0, 12]}], [3, 14, {"cores": 17, "ethernet": [0, 12]}], [3, 15, {"cores": 17, "ethernet": [0, 12]}], [3, 16, {"cores": 17, "ethernet": [0, 12]}], [3, 17, {"cores": 17, "ethernet": [0, 12]}], [3, 18, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [3, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [3, 25, {"cores": 17, "ethernet": [0, 24]}], [3, 26, {"cores": 17, "ethernet": [0, 24]}], [3, 27, {"cores": 17, "ethernet": [0, 24]}], [3, 28, {"cores": 17, "ethernet": [0, 24]}], [3, 29, {"cores": 17, "ethernet": [0, 24]}], [3, 30, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [4, 0, {"cores": 16, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 17, "ethernet": [0, 0]}], [4, 2, {"cores": 17, "ethernet": [0, 0]}], [4, 3, {"cores": 17, "ethernet": [0, 0]}], [4, 4, {"cores": 17, "ethernet": [0, 0]}], [4, 5, {"cores": 17, "ethernet": [0, 0]}], [4, 6, {"cores": 17, "ethernet": [0, 0]}], [4, 7, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [4, 8, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4], "ipAddress": "10.11.197.73"}], [4, 9, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 10, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [4, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [1]}], [4, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [0]}], [4, 15, {"cores": 17, "ethernet": [0, 12]}], [4, 16, {"cores": 17, "ethernet": [0, 12]}], [4, 17, {"cores": 17, "ethernet": [0, 12]}], [4, 18, {"cores": 17, "ethernet": [0, 12]}], [4, 19, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [4, 20, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4], "ipAddress": "10.11.196.89"}], [4, 21, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4]}], [4, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1, 3, 4]}], [4, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 3, 4]}], [4, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4]}], [4, 25, {"cores": 17, "ethernet": [0, 24]}], [4, 26, {"cores": 17, "ethernet": [0, 24]}], [4, 27, {"cores": 17, "ethernet": [0, 24]}], [4, 28, {"cores": 17, "ethernet": [0, 24]}], [4, 29, {"cores": 17, "ethernet": [0, 24]}], [4, 30, {"cores": 17, "ethernet": [0, 24]}], [4, 31, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3]}], [4, 32, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4], "ipAddress": "10.11.196.73"}], [4, 33, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 34, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3, 4]}], [5, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 17, "ethernet": [0, 0]}], [5, 4, {"cores": 16, "ethernet": [0, 0]}], [5, 5, {"cores": 17, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 17, "ethernet": [0, 0]}], [5, 8, {"cores": 17, "ethernet": [4, 8]}], [5, 9, {"cores": 17, "ethernet": [4, 8]}], [5, 10, {"cores": 17, "ethernet": [4, 8]}], [5, 11, {"cores": 17, "ethernet": [4, 8]}], [5, 12, {"cores": 17, "ethernet": [4, 8]}], [5, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2]}], [5, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [5]}], [5, 16, {"cores": 17, "ethernet": [0, 12]}], [5, 17, {"cores": 17, "ethernet": [0, 12]}], [5, 18, {"cores": 17, "ethernet": [0, 12]}], [5, 19, {"cores": 17, "ethernet": [0, 12]}], [5, 20, {"cores": 17, "ethernet": [4, 20]}], [5, 21, {"cores": 17, "ethernet": [4, 20]}], [5, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [2]}], [5, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [5]}], [5, 25, {"cores": 17, "ethernet": [0, 24]}], [5, 26, {"cores": 17, "ethernet": [0, 24]}], [5, 27, {"cores": 17, "ethernet": [0, 24]}], [5, 28, {"cores": 17, "ethernet": [0, 24]}], [5, 29, {"cores": 17, "ethernet": [0, 24]}], [5, 30, {"cores": 17, "ethernet": [0, 24]}], [5, 31, {"cores": 17, "ethernet": [0, 24]}], [5, 32, {"cores": 17, "ethernet": [4, 32]}], [5, 33, {"cores": 17, "ethernet": [4, 32]}], [5, 34, {"cores": 17, "ethernet": [4, 32]}], [5, 35, {"cores": 17, "ethernet": [4, 32]}], [5, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [6, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 17, "ethernet": [0, 0]}], [6, 5, {"cores": 17, "ethernet": [0, 0]}], [6, 6, {"cores": 17, "ethernet": [0, 0]}], [6, 7, {"cores": 17, "ethernet": [0, 0]}], [6, 8, {"cores": 17, "ethernet": [4, 8]}], [6, 9, {"cores": 17, "ethernet": [4, 8]}], [6, 10, {"cores": 17, "ethernet": [4, 8]}], [6, 11, {"cores": 17, "ethernet": [4, 8]}], [6, 12, {"cores": 17, "ethernet": [4, 8]}], [6, 13, {"cores": 17, "ethernet": [4, 8]}], [6, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [6, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [6, 16, {"cores": 17, "ethernet": [0, 12]}], [6, 17, {"cores": 17, "ethernet": [0, 12]}], [6, 18, {"cores": 17, "ethernet": [0, 12]}], [6, 19, {"cores": 17, "ethernet": [0, 12]}], [6, 20, {"cores": 17, "ethernet": [4, 20]}], [6, 21, {"cores": 17, "ethernet": [4, 20]}], [6, 22, {"cores": 17, "ethernet": [4, 20]}], [6, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3]}], [6, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [4]}], [6, 25, {"cores": 17, "ethernet": [4, 20]}], [6, 26, {"cores": 17, "ethernet": [0, 24]}], [6, 27, {"cores": 17, "ethernet": [0, 24]}], [6, 28, {"cores": 17, "ethernet": [0, 24]}], [6, 29, {"cores": 17, "ethernet": [0, 24]}], [6, 30, {"cores": 17, "ethernet": [0, 24]}], [6, 31, {"cores": 17, "ethernet": [0, 24]}], [6, 32, {"cores": 17, "ethernet": [4, 32]}], [6, 33, {"cores": 17, "ethernet": [4, 32]}], [6, 34, {"cores": 17, "ethernet": [4, 32]}], [6, 35, {"cores": 17, "ethernet": [4, 32]}], [6, 36, {"cores": 17, "ethernet": [4, 32]}], [6, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [7, 4, {"cores": 17, "ethernet": [0, 0]}], [7, 5, {"cores": 17, "ethernet": [0, 0]}], [7, 6, {"cores": 17, "ethernet": [0, 0]}], [7, 7, {"cores": 17, "ethernet": [0, 0]}], [7, 8, {"cores": 17, "ethernet": [4, 8]}], [7, 9, {"cores": 17, "ethernet": [4, 8]}], [7, 10, {"cores": 17, "ethernet": [4, 8]}], [7, 11, {"cores": 17, "ethernet": [4, 8]}], [7, 12, {"cores": 17, "ethernet": [4, 8]}], [7, 13, {"cores": 17, "ethernet": [4, 8]}], [7, 14, {"cores": 17, "ethernet": [4, 8]}], [7, 15, {"cores": 17, "ethernet": [0, 12]}], [7, 16, {"cores": 17, "ethernet": [0, 12]}], [7, 17, {"cores": 17, "ethernet": [0, 12]}], [7, 18, {"cores": 17, "ethernet": [0, 12]}], [7, 19, {"cores": 17, "ethernet": [0, 12]}], [7, 20, {"cores": 17, "ethernet": [4, 20]}], [7, 21, {"cores": 17, "ethernet": [4, 20]}], [7, 22, {"cores": 17, "ethernet": [4, 20]}], [7, 23, {"cores": 17, "ethernet": [4, 20]}], [7, 24, {"cores": 17, "ethernet": [4, 20]}], [7, 25, {"cores": 17, "ethernet": [4, 20]}], [7, 26, {"cores": 17, "ethernet": [4, 20]}], [7, 27, {"cores": 17, "ethernet": [0, 24]}], [7, 28, {"cores": 17, "ethernet": [0, 24]}], [7, 29, {"cores": 17, "ethernet": [0, 24]}], [7, 30, {"cores": 17, "ethernet": [0, 24]}], [7, 31, {"cores": 17, "ethernet": [0, 24]}], [7, 32, {"cores": 17, "ethernet": [4, 32]}], [7, 33, {"cores": 17, "ethernet": [4, 32]}], [7, 34, {"cores": 17, "ethernet": [4, 32]}], [7, 35, {"cores": 17, "ethernet": [4, 32]}], [7, 36, {"cores": 17, "ethernet": [4, 32]}], [7, 37, {"cores": 17, "ethernet": [4, 32]}], [7, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [8, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [5], "ipAddress": "10.11.197.137"}], [8, 5, {"cores": 17, "ethernet": [8, 4]}], [8, 6, {"cores": 17, "ethernet": [8, 4]}], [8, 7, {"cores": 17, "ethernet": [8, 4]}], [8, 8, {"cores": 17, "ethernet": [4, 8]}], [8, 9, {"cores": 17, "ethernet": [4, 8]}], [8, 10, {"cores": 17, "ethernet": [4, 8]}], [8, 11, {"cores": 17, "ethernet": [4, 8]}], [8, 12, {"cores": 17, "ethernet": [4, 8]}], [8, 13, {"cores": 17, "ethernet": [4, 8]}], [8, 14, {"cores": 17, "ethernet": [4, 8]}], [8, 15, {"cores": 17, "ethernet": [4, 8]}], [8, 16, {"cores": 17, "ethernet": [8, 16], "ipAddress": "10.11.196.153"}], [8, 17, {"cores": 17, "ethernet": [8, 16]}], [8, 18, {"cores": 17, "ethernet": [8, 16]}], [8, 19, {"cores": 17, "ethernet": [8, 16]}], [8, 20, {"cores": 17, "ethernet": [4, 20]}], [8, 21, {"cores": 17, "ethernet": [4, 20]}], [8, 22, {"cores": 17, "ethernet": [4, 20]}], [8, 23, {"cores": 17, "ethernet": [4, 20]}], [8, 24, {"cores": 17, "ethernet": [4, 20]}], [8, 25, {"cores": 17, "ethernet": [4, 20]}], [8, 26, {"cores": 17, "ethernet": [4, 20]}], [8, 27, {"cores": 17, "ethernet": [4, 20]}], [8, 28, {"cores": 17, "ethernet": [8, 28], "ipAddress": "10.11.196.137"}], [8, 29, {"cores": 17, "ethernet": [8, 28]}], [8, 30, {"cores": 17, "ethernet": [8, 28]}], [8, 31, {"cores": 17, "ethernet": [8, 28]}], [8, 32, {"cores": 17, "ethernet": [4, 32]}], [8, 33, {"cores": 17, "ethernet": [4, 32]}], [8, 34, {"cores": 17, "ethernet": [4, 32]}], [8, 35, {"cores": 17, "ethernet": [4, 32]}], [8, 36, {"cores": 17, "ethernet": [4, 32]}], [8, 37, {"cores": 17, "ethernet": [4, 32]}], [8, 38, {"cores": 17, "ethernet": [4, 32]}], [8, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2, 3]}], [9, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [9, 5, {"cores": 17, "ethernet": [8, 4]}], [9, 6, {"cores": 17, "ethernet": [8, 4]}], [9, 7, {"cores": 17, "ethernet": [8, 4]}], [9, 8, {"cores": 17, "ethernet": [8, 4]}], [9, 9, {"cores": 17, "ethernet": [4, 8]}], [9, 10, {"cores": 17, "ethernet": [4, 8]}], [9, 11, {"cores": 17, "ethernet": [4, 8]}], [9, 12, {"cores": 17, "ethernet": [4, 8]}], [9, 13, {"cores": 17, "ethernet": [4, 8]}], [9, 14, {"cores": 17, "ethernet": [4, 8]}], [9, 15, {"cores": 17, "ethernet": [4, 8]}], [9, 16, {"cores": 17, "ethernet": [8, 16]}], [9, 17, {"cores": 17, "ethernet": [8, 16]}], [9, 18, {"cores": 17, "ethernet": [8, 16]}], [9, 19, {"cores": 17, "ethernet": [8, 16]}], [9, 20, {"cores": 17, "ethernet": [8, 16]}], [9, 21, {"cores": 17, "ethernet": [4, 20]}], [9, 22, {"cores": 17, "ethernet": [4, 20]}], [9, 23, {"cores": 17, "ethernet": [4, 20]}], [9, 24, {"cores": 17, "ethernet": [4, 20]}], [9, 25, {"cores": 17, "ethernet": [4, 20]}], [9, 26, {"cores": 17, "ethernet": [4, 20]}], [9, 27, {"cores": 17, "ethernet": [4, 20]}], [9, 28, {"cores": 17, "ethernet": [8, 28]}], [9, 29, {"cores": 17, "ethernet": [8, 28]}], [9, 30, {"cores": 17, "ethernet": [8, 28]}], [9, 31, {"cores": 17, "ethernet": [8, 28]}], [9, 32, {"cores": 17, "ethernet": [8, 28]}], [9, 33, {"cores": 17, "ethernet": [4, 32]}], [9, 34, {"cores": 17, "ethernet": [4, 32]}], [9, 35, {"cores": 17, "ethernet": [4, 32]}], [9, 36, {"cores": 17, "ethernet": [4, 32]}], [9, 37, {"cores": 17, "ethernet": [4, 32]}], [9, 38, {"cores": 15, "ethernet": [4, 32]}], [9, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [10, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [10, 5, {"cores": 17, "ethernet": [8, 4]}], [10, 6, {"cores": 17, "ethernet": [8, 4]}], [10, 7, {"cores": 17, "ethernet": [8, 4]}], [10, 8, {"cores": 17, "ethernet": [8, 4]}], [10, 9, {"cores": 17, "ethernet": [8, 4]}], [10, 10, {"cores": 17, "ethernet": [4, 8]}], [10, 11, {"cores": 17, "ethernet": [4, 8]}], [10, 12, {"cores": 17, "ethernet": [4, 8]}], [10, 13, {"cores": 17, "ethernet": [4, 8]}], [10, 14, {"cores": 17, "ethernet": [4, 8]}], [10, 15, {"cores": 17, "ethernet": [4, 8]}], [10, 16, {"cores": 17, "ethernet": [8, 16]}], [10, 17, {"cores": 17, "ethernet": [8, 16]}], [10, 18, {"cores": 17, "ethernet": [8, 16]}], [10, 19, {"cores": 17, "ethernet": [8, 16]}], [10, 20, {"cores": 17, "ethernet": [8, 16]}], [10, 21, {"cores": 17, "ethernet": [8, 16]}], [10, 22, {"cores": 17, "ethernet": [4, 20]}], [10, 23, {"cores": 17, "ethernet": [4, 20]}], [10, 24, {"cores": 17, "ethernet": [4, 20]}], [10, 25, {"cores": 17, "ethernet": [4, 20]}], [10, 26, {"cores": 17, "ethernet": [4, 20]}], [10, 27, {"cores": 17, "ethernet": [4, 20]}], [10, 28, {"cores": 17, "ethernet": [8, 28]}], [10, 29, {"cores": 17, "ethernet": [8, 28]}], [10, 30, {"cores": 17, "ethernet": [8, 28]}], [10, 31, {"cores": 17, "ethernet": [8, 28]}], [10, 32, {"cores": 17, "ethernet": [8, 28]}], [10, 33, {"cores": 17, "ethernet": [8, 28]}], [10, 34, {"cores": 17, "ethernet": [4, 32]}], [10, 35, {"cores": 17, "ethernet": [4, 32]}], [10, 36, {"cores": 17, "ethernet": [4, 32]}], [10, 37, {"cores": 17, "ethernet": [4, 32]}], [10, 38, {"cores": 17, "ethernet": [4, 32]}], [10, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [11, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [11, 5, {"cores": 17, "ethernet": [8, 4]}], [11, 6, {"cores": 17, "ethernet": [8, 4]}], [11, 7, {"cores": 17, "ethernet": [8, 4]}], [11, 8, {"cores": 17, "ethernet": [8, 4]}], [11, 9, {"cores": 17, "ethernet": [8, 4]}], [11, 10, {"cores": 17, "ethernet": [8, 4]}], [11, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [1]}], [11, 12, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 13, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 14, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 15, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0]}], [11, 16, {"cores": 17, "ethernet": [8, 16]}], [11, 17, {"cores": 17, "ethernet": [8, 16]}], [11, 18, {"cores": 17, "ethernet": [8, 16]}], [11, 19, {"cores": 17, "ethernet": [8, 16]}], [11, 20, {"cores": 17, "ethernet": [8, 16]}], [11, 21, {"cores": 17, "ethernet": [8, 16]}], [11, 22, {"cores": 17, "ethernet": [8, 16]}], [11, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1]}], [11, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 25, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 26, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 27, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0]}], [11, 28, {"cores": 17, "ethernet": [8, 28]}], [11, 29, {"cores": 17, "ethernet": [8, 28]}], [11, 30, {"cores": 17, "ethernet": [8, 28]}], [11, 31, {"cores": 17, "ethernet": [8, 28]}], [11, 32, {"cores": 17, "ethernet": [8, 28]}], [11, 33, {"cores": 17, "ethernet": [8, 28]}], [11, 34, {"cores": 17, "ethernet": [8, 28]}], [11, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1]}], [11, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1, 2]}], [12, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 4, 5]}], [12, 5, {"cores": 17, "ethernet": [8, 4]}], [12, 6, {"cores": 17, "ethernet": [8, 4]}], [12, 7, {"cores": 17, "ethernet": [8, 4]}], [12, 8, {"cores": 17, "ethernet": [8, 4]}], [12, 9, {"cores": 17, "ethernet": [8, 4]}], [12, 10, {"cores": 17, "ethernet": [8, 4]}], [12, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [12, 16, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 17, {"cores": 17, "ethernet": [8, 16]}], [12, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [2]}], [12, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 20, {"cores": 17, "ethernet": [8, 16]}], [12, 21, {"cores": 17, "ethernet": [8, 16]}], [12, 22, {"cores": 17, "ethernet": [8, 16]}], [12, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [12, 28, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [12, 29, {"cores": 17, "ethernet": [8, 28]}], [12, 30, {"cores": 17, "ethernet": [8, 28]}], [12, 31, {"cores": 17, "ethernet": [8, 28]}], [12, 32, {"cores": 17, "ethernet": [8, 28]}], [12, 33, {"cores": 17, "ethernet": [8, 28]}], [12, 34, {"cores": 17, "ethernet": [8, 28]}], [12, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [13, 5, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [13, 6, {"cores": 17, "ethernet": [8, 4]}], [13, 7, {"cores": 17, "ethernet": [8, 4]}], [13, 8, {"cores": 17, "ethernet": [8, 4]}], [13, 9, {"cores": 17, "ethernet": [8, 4]}], [13, 10, {"cores": 17, "ethernet": [8, 4]}], [13, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [13, 17, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [13, 18, {"cores": 17, "ethernet": [8, 16]}], [13, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [3]}], [13, 20, {"cores": 17, "ethernet": [8, 16]}], [13, 21, {"cores": 17, "ethernet": [8, 16]}], [13, 22, {"cores": 17, "ethernet": [8, 16]}], [13, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [13, 29, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [13, 30, {"cores": 17, "ethernet": [8, 28]}], [13, 31, {"cores": 17, "ethernet": [8, 28]}], [13, 32, {"cores": 17, "ethernet": [8, 28]}], [13, 33, {"cores": 17, "ethernet": [8, 28]}], [13, 34, {"cores": 17, "ethernet": [8, 28]}], [13, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [14, 6, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [14, 7, {"cores": 17, "ethernet": [8, 4]}], [14, 8, {"cores": 17, "ethernet": [8, 4]}], [14, 9, {"cores": 17, "ethernet": [8, 4]}], [14, 10, {"cores": 17, "ethernet": [8, 4]}], [14, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [14, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [14, 19, {"cores": 17, "ethernet": [8, 16]}], [14, 20, {"cores": 17, "ethernet": [8, 16]}], [14, 21, {"cores": 17, "ethernet": [8, 16]}], [14, 22, {"cores": 17, "ethernet": [8, 16]}], [14, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [14, 30, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [14, 31, {"cores": 17, "ethernet": [8, 28]}], [14, 32, {"cores": 17, "ethernet": [8, 28]}], [14, 33, {"cores": 17, "ethernet": [8, 28]}], [14, 34, {"cores": 17, "ethernet": [8, 28]}], [14, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [15, 7, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 5]}], [15, 8, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 9, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 10, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 2]}], [15, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 5]}], [15, 20, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 21, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 22, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 2]}], [15, 31, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 5]}], [15, 32, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 33, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 34, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 40, "width": 16, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "10.11.197.9"}], [0, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [0, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.25"}], [0, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3, 4]}], [0, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3, 4]}], [0, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4, 5], "ipAddress": "10.11.196.9"}], [0, 25, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 26, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3, 4]}], [0, 27, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [1, 4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0]}], [1, 2, {"cores": 17, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [1, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [1, 13, {"cores": 17, "ethernet": [0, 12]}], [1, 14, {"cores": 17, "ethernet": [0, 12]}], [1, 15, {"cores": 17, "ethernet": [0, 12]}], [1, 16, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [1, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [1, 25, {"cores": 17, "ethernet": [0, 24]}], [1, 26, {"cores": 17, "ethernet": [0, 24]}], [1, 27, {"cores": 17, "ethernet": [0, 24]}], [1, 28, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [2, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 4, 5]}], [2, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [5]}], [2, 3, {"cores": 17, "ethernet": [0, 0]}], [2, 4, {"cores": 17, "ethernet": [0, 0]}], [2, 5, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [2, 13, {"cores": 17, "ethernet": [0, 12]}], [2, 14, {"cores": 17, "ethernet": [0, 12]}], [2, 15, {"cores": 17, "ethernet": [0, 12]}], [2, 16, {"cores": 17, "ethernet": [0, 12]}], [2, 17, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [2, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [2, 25, {"cores": 17, "ethernet": [0, 24]}], [2, 26, {"cores": 17, "ethernet": [0, 24]}], [2, 27, {"cores": 17, "ethernet": [0, 24]}], [2, 28, {"cores": 17, "ethernet": [0, 24]}], [2, 29, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [3, 0, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [3, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [4]}], [3, 3, {"cores": 16, "ethernet": [0, 0]}], [3, 4, {"cores": 17, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4, 5]}], [3, 13, {"cores": 17, "ethernet": [0, 12]}], [3, 14, {"cores": 17, "ethernet": [0, 12]}], [3, 15, {"cores": 17, "ethernet": [0, 12]}], [3, 16, {"cores": 17, "ethernet": [0, 12]}], [3, 17, {"cores": 17, "ethernet": [0, 12]}], [3, 18, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2, 3]}], [3, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4, 5]}], [3, 25, {"cores": 17, "ethernet": [0, 24]}], [3, 26, {"cores": 17, "ethernet": [0, 24]}], [3, 27, {"cores": 17, "ethernet": [0, 24]}], [3, 28, {"cores": 17, "ethernet": [0, 24]}], [3, 29, {"cores": 17, "ethernet": [0, 24]}], [3, 30, {"cores": 17, "ethernet": [0, 24], "deadLinks": [2, 3]}], [4, 0, {"cores": 16, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 17, "ethernet": [0, 0]}], [4, 2, {"cores": 17, "ethernet": [0, 0]}], [4, 3, {"cores": 17, "ethernet": [0, 0]}], [4, 4, {"cores": 17, "ethernet": [0, 0]}], [4, 5, {"cores": 17, "ethernet": [0, 0]}], [4, 6, {"cores": 17, "ethernet": [0, 0]}], [4, 7, {"cores": 17, "ethernet": [0, 0], "deadLinks": [3]}], [4, 8, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4], "ipAddress": "10.11.197.73"}], [4, 9, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 10, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [3, 4]}], [4, 12, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [4, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [1]}], [4, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [0]}], [4, 15, {"cores": 17, "ethernet": [0, 12]}], [4, 16, {"cores": 17, "ethernet": [0, 12]}], [4, 17, {"cores": 17, "ethernet": [0, 12]}], [4, 18, {"cores": 17, "ethernet": [0, 12]}], [4, 19, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [4, 20, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4], "ipAddress": "10.11.196.89"}], [4, 21, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3, 4]}], [4, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1, 3, 4]}], [4, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 3, 4]}], [4, 24, {"cores": 17, "ethernet": [0, 24], "deadLinks": [4]}], [4, 25, {"cores": 17, "ethernet": [0, 24]}], [4, 26, {"cores": 17, "ethernet": [0, 24]}], [4, 27, {"cores": 17, "ethernet": [0, 24]}], [4, 28, {"cores": 17, "ethernet": [0, 24]}], [4, 29, {"cores": 17, "ethernet": [0, 24]}], [4, 30, {"cores": 17, "ethernet": [0, 24]}], [4, 31, {"cores": 17, "ethernet": [0, 24], "deadLinks": [3]}], [4, 32, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4], "ipAddress": "10.11.196.73"}], [4, 33, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 34, {"cores": 17, "ethernet": [4, 32], "deadLinks": [3, 4]}], [4, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3, 4]}], [5, 1, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 17, "ethernet": [0, 0]}], [5, 4, {"cores": 16, "ethernet": [0, 0]}], [5, 5, {"cores": 17, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 17, "ethernet": [0, 0]}], [5, 8, {"cores": 17, "ethernet": [4, 8]}], [5, 9, {"cores": 17, "ethernet": [4, 8]}], [5, 10, {"cores": 17, "ethernet": [4, 8]}], [5, 11, {"cores": 17, "ethernet": [4, 8]}], [5, 12, {"cores": 17, "ethernet": [4, 8]}], [5, 13, {"cores": 17, "ethernet": [0, 12], "deadLinks": [2]}], [5, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [5]}], [5, 16, {"cores": 17, "ethernet": [0, 12]}], [5, 17, {"cores": 17, "ethernet": [0, 12]}], [5, 18, {"cores": 17, "ethernet": [0, 12]}], [5, 19, {"cores": 17, "ethernet": [0, 12]}], [5, 20, {"cores": 17, "ethernet": [4, 20]}], [5, 21, {"cores": 17, "ethernet": [4, 20]}], [5, 22, {"cores": 17, "ethernet": [4, 20], "deadLinks": [2]}], [5, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [5]}], [5, 25, {"cores": 17, "ethernet": [0, 24]}], [5, 26, {"cores": 17, "ethernet": [0, 24]}], [5, 27, {"cores": 17, "ethernet": [0, 24]}], [5, 28, {"cores": 17, "ethernet": [0, 24]}], [5, 29, {"cores": 17, "ethernet": [0, 24]}], [5, 30, {"cores": 17, "ethernet": [0, 24]}], [5, 31, {"cores": 17, "ethernet": [0, 24]}], [5, 32, {"cores": 17, "ethernet": [4, 32]}], [5, 33, {"cores": 17, "ethernet": [4, 32]}], [5, 34, {"cores": 17, "ethernet": [4, 32]}], [5, 35, {"cores": 17, "ethernet": [4, 32]}], [5, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [6, 2, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 17, "ethernet": [0, 0]}], [6, 4, {"cores": 17, "ethernet": [0, 0]}], [6, 5, {"cores": 17, "ethernet": [0, 0]}], [6, 6, {"cores": 17, "ethernet": [0, 0]}], [6, 7, {"cores": 17, "ethernet": [0, 0]}], [6, 8, {"cores": 17, "ethernet": [4, 8]}], [6, 9, {"cores": 17, "ethernet": [4, 8]}], [6, 10, {"cores": 17, "ethernet": [4, 8]}], [6, 11, {"cores": 17, "ethernet": [4, 8]}], [6, 12, {"cores": 17, "ethernet": [4, 8]}], [6, 13, {"cores": 17, "ethernet": [4, 8]}], [6, 14, {"cores": 17, "ethernet": [0, 12], "deadLinks": [3]}], [6, 15, {"cores": 17, "ethernet": [0, 12], "deadLinks": [4]}], [6, 16, {"cores": 17, "ethernet": [0, 12]}], [6, 17, {"cores": 17, "ethernet": [0, 12]}], [6, 18, {"cores": 17, "ethernet": [0, 12]}], [6, 19, {"cores": 17, "ethernet": [0, 12]}], [6, 20, {"cores": 17, "ethernet": [4, 20]}], [6, 21, {"cores": 17, "ethernet": [4, 20]}], [6, 22, {"cores": 17, "ethernet": [4, 20]}], [6, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [3]}], [6, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [4]}], [6, 25, {"cores": 17, "ethernet": [4, 20]}], [6, 26, {"cores": 17, "ethernet": [0, 24]}], [6, 27, {"cores": 17, "ethernet": [0, 24]}], [6, 28, {"cores": 17, "ethernet": [0, 24]}], [6, 29, {"cores": 17, "ethernet": [0, 24]}], [6, 30, {"cores": 17, "ethernet": [0, 24]}], [6, 31, {"cores": 17, "ethernet": [0, 24]}], [6, 32, {"cores": 17, "ethernet": [4, 32]}], [6, 33, {"cores": 17, "ethernet": [4, 32]}], [6, 34, {"cores": 17, "ethernet": [4, 32]}], [6, 35, {"cores": 17, "ethernet": [4, 32]}], [6, 36, {"cores": 17, "ethernet": [4, 32]}], [6, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [7, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [0, 5]}], [7, 4, {"cores": 17, "ethernet": [0, 0]}], [7, 5, {"cores": 17, "ethernet": [0, 0]}], [7, 6, {"cores": 17, "ethernet": [0, 0]}], [7, 7, {"cores": 17, "ethernet": [0, 0]}], [7, 8, {"cores": 17, "ethernet": [4, 8]}], [7, 9, {"cores": 17, "ethernet": [4, 8]}], [7, 10, {"cores": 17, "ethernet": [4, 8]}], [7, 11, {"cores": 17, "ethernet": [4, 8]}], [7, 12, {"cores": 17, "ethernet": [4, 8]}], [7, 13, {"cores": 17, "ethernet": [4, 8]}], [7, 14, {"cores": 17, "ethernet": [4, 8]}], [7, 15, {"cores": 17, "ethernet": [0, 12]}], [7, 16, {"cores": 17, "ethernet": [0, 12]}], [7, 17, {"cores": 17, "ethernet": [0, 12]}], [7, 18, {"cores": 17, "ethernet": [0, 12]}], [7, 19, {"cores": 17, "ethernet": [0, 12]}], [7, 20, {"cores": 17, "ethernet": [4, 20]}], [7, 21, {"cores": 17, "ethernet": [4, 20]}], [7, 22, {"cores": 17, "ethernet": [4, 20]}], [7, 23, {"cores": 17, "ethernet": [4, 20]}], [7, 24, {"cores": 17, "ethernet": [4, 20]}], [7, 25, {"cores": 17, "ethernet": [4, 20]}], [7, 26, {"cores": 17, "ethernet": [4, 20]}], [7, 27, {"cores": 17, "ethernet": [0, 24]}], [7, 28, {"cores": 17, "ethernet": [0, 24]}], [7, 29, {"cores": 17, "ethernet": [0, 24]}], [7, 30, {"cores": 17, "ethernet": [0, 24]}], [7, 31, {"cores": 17, "ethernet": [0, 24]}], [7, 32, {"cores": 17, "ethernet": [4, 32]}], [7, 33, {"cores": 17, "ethernet": [4, 32]}], [7, 34, {"cores": 17, "ethernet": [4, 32]}], [7, 35, {"cores": 17, "ethernet": [4, 32]}], [7, 36, {"cores": 17, "ethernet": [4, 32]}], [7, 37, {"cores": 17, "ethernet": [4, 32]}], [7, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [2, 3]}], [8, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [5], "ipAddress": "10.11.197.137"}], [8, 5, {"cores": 17, "ethernet": [8, 4]}], [8, 6, {"cores": 17, "ethernet": [8, 4]}], [8, 7, {"cores": 17, "ethernet": [8, 4]}], [8, 8, {"cores": 17, "ethernet": [4, 8]}], [8, 9, {"cores": 17, "ethernet": [4, 8]}], [8, 10, {"cores": 17, "ethernet": [4, 8]}], [8, 11, {"cores": 17, "ethernet": [4, 8]}], [8, 12, {"cores": 17, "ethernet": [4, 8]}], [8, 13, {"cores": 17, "ethernet": [4, 8]}], [8, 14, {"cores": 17, "ethernet": [4, 8]}], [8, 15, {"cores": 17, "ethernet": [4, 8]}], [8, 16, {"cores": 17, "ethernet": [8, 16], "ipAddress": "10.11.196.153"}], [8, 17, {"cores": 17, "ethernet": [8, 16]}], [8, 18, {"cores": 17, "ethernet": [8, 16]}], [8, 19, {"cores": 17, "ethernet": [8, 16]}], [8, 20, {"cores": 17, "ethernet": [4, 20]}], [8, 21, {"cores": 17, "ethernet": [4, 20]}], [8, 22, {"cores": 17, "ethernet": [4, 20]}], [8, 23, {"cores": 17, "ethernet": [4, 20]}], [8, 24, {"cores": 17, "ethernet": [4, 20]}], [8, 25, {"cores": 17, "ethernet": [4, 20]}], [8, 26, {"cores": 17, "ethernet": [4, 20]}], [8, 27, {"cores": 17, "ethernet": [4, 20]}], [8, 28, {"cores": 17, "ethernet": [8, 28], "ipAddress": "10.11.196.137"}], [8, 29, {"cores": 17, "ethernet": [8, 28]}], [8, 30, {"cores": 17, "ethernet": [8, 28]}], [8, 31, {"cores": 17, "ethernet": [8, 28]}], [8, 32, {"cores": 17, "ethernet": [4, 32]}], [8, 33, {"cores": 17, "ethernet": [4, 32]}], [8, 34, {"cores": 17, "ethernet": [4, 32]}], [8, 35, {"cores": 17, "ethernet": [4, 32]}], [8, 36, {"cores": 17, "ethernet": [4, 32]}], [8, 37, {"cores": 17, "ethernet": [4, 32]}], [8, 38, {"cores": 17, "ethernet": [4, 32]}], [8, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2, 3]}], [9, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [9, 5, {"cores": 17, "ethernet": [8, 4]}], [9, 6, {"cores": 17, "ethernet": [8, 4]}], [9, 7, {"cores": 17, "ethernet": [8, 4]}], [9, 8, {"cores": 17, "ethernet": [8, 4]}], [9, 9, {"cores": 17, "ethernet": [4, 8]}], [9, 10, {"cores": 17, "ethernet": [4, 8]}], [9, 11, {"cores": 17, "ethernet": [4, 8]}], [9, 12, {"cores": 17, "ethernet": [4, 8]}], [9, 13, {"cores": 17, "ethernet": [4, 8]}], [9, 14, {"cores": 17, "ethernet": [4, 8]}], [9, 15, {"cores": 17, "ethernet": [4, 8]}], [9, 16, {"cores": 17, "ethernet": [8, 16]}], [9, 17, {"cores": 17, "ethernet": [8, 16]}], [9, 18, {"cores": 17, "ethernet": [8, 16]}], [9, 19, {"cores": 17, "ethernet": [8, 16]}], [9, 20, {"cores": 17, "ethernet": [8, 16]}], [9, 21, {"cores": 17, "ethernet": [4, 20]}], [9, 22, {"cores": 17, "ethernet": [4, 20]}], [9, 23, {"cores": 17, "ethernet": [4, 20]}], [9, 24, {"cores": 17, "ethernet": [4, 20]}], [9, 25, {"cores": 17, "ethernet": [4, 20]}], [9, 26, {"cores": 17, "ethernet": [4, 20]}], [9, 27, {"cores": 17, "ethernet": [4, 20]}], [9, 28, {"cores": 17, "ethernet": [8, 28]}], [9, 29, {"cores": 17, "ethernet": [8, 28]}], [9, 30, {"cores": 17, "ethernet": [8, 28]}], [9, 31, {"cores": 17, "ethernet": [8, 28]}], [9, 32, {"cores": 17, "ethernet": [8, 28]}], [9, 33, {"cores": 17, "ethernet": [4, 32]}], [9, 34, {"cores": 17, "ethernet": [4, 32]}], [9, 35, {"cores": 17, "ethernet": [4, 32]}], [9, 36, {"cores": 17, "ethernet": [4, 32]}], [9, 37, {"cores": 17, "ethernet": [4, 32]}], [9, 38, {"cores": 15, "ethernet": [4, 32]}], [9, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [10, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [10, 5, {"cores": 17, "ethernet": [8, 4]}], [10, 6, {"cores": 17, "ethernet": [8, 4]}], [10, 7, {"cores": 17, "ethernet": [8, 4]}], [10, 8, {"cores": 17, "ethernet": [8, 4]}], [10, 9, {"cores": 17, "ethernet": [8, 4]}], [10, 10, {"cores": 17, "ethernet": [4, 8]}], [10, 11, {"cores": 17, "ethernet": [4, 8]}], [10, 12, {"cores": 17, "ethernet": [4, 8]}], [10, 13, {"cores": 17, "ethernet": [4, 8]}], [10, 14, {"cores": 17, "ethernet": [4, 8]}], [10, 15, {"cores": 17, "ethernet": [4, 8]}], [10, 16, {"cores": 17, "ethernet": [8, 16]}], [10, 17, {"cores": 17, "ethernet": [8, 16]}], [10, 18, {"cores": 17, "ethernet": [8, 16]}], [10, 19, {"cores": 17, "ethernet": [8, 16]}], [10, 20, {"cores": 17, "ethernet": [8, 16]}], [10, 21, {"cores": 17, "ethernet": [8, 16]}], [10, 22, {"cores": 17, "ethernet": [4, 20]}], [10, 23, {"cores": 17, "ethernet": [4, 20]}], [10, 24, {"cores": 17, "ethernet": [4, 20]}], [10, 25, {"cores": 17, "ethernet": [4, 20]}], [10, 26, {"cores": 17, "ethernet": [4, 20]}], [10, 27, {"cores": 17, "ethernet": [4, 20]}], [10, 28, {"cores": 17, "ethernet": [8, 28]}], [10, 29, {"cores": 17, "ethernet": [8, 28]}], [10, 30, {"cores": 17, "ethernet": [8, 28]}], [10, 31, {"cores": 17, "ethernet": [8, 28]}], [10, 32, {"cores": 17, "ethernet": [8, 28]}], [10, 33, {"cores": 17, "ethernet": [8, 28]}], [10, 34, {"cores": 17, "ethernet": [4, 32]}], [10, 35, {"cores": 17, "ethernet": [4, 32]}], [10, 36, {"cores": 17, "ethernet": [4, 32]}], [10, 37, {"cores": 17, "ethernet": [4, 32]}], [10, 38, {"cores": 17, "ethernet": [4, 32]}], [10, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1, 2]}], [11, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [4, 5]}], [11, 5, {"cores": 17, "ethernet": [8, 4]}], [11, 6, {"cores": 17, "ethernet": [8, 4]}], [11, 7, {"cores": 17, "ethernet": [8, 4]}], [11, 8, {"cores": 17, "ethernet": [8, 4]}], [11, 9, {"cores": 17, "ethernet": [8, 4]}], [11, 10, {"cores": 17, "ethernet": [8, 4]}], [11, 11, {"cores": 17, "ethernet": [4, 8], "deadLinks": [1]}], [11, 12, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 13, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 14, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0, 1]}], [11, 15, {"cores": 17, "ethernet": [4, 8], "deadLinks": [0]}], [11, 16, {"cores": 17, "ethernet": [8, 16]}], [11, 17, {"cores": 17, "ethernet": [8, 16]}], [11, 18, {"cores": 17, "ethernet": [8, 16]}], [11, 19, {"cores": 17, "ethernet": [8, 16]}], [11, 20, {"cores": 17, "ethernet": [8, 16]}], [11, 21, {"cores": 17, "ethernet": [8, 16]}], [11, 22, {"cores": 17, "ethernet": [8, 16]}], [11, 23, {"cores": 17, "ethernet": [4, 20], "deadLinks": [1]}], [11, 24, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 25, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 26, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0, 1]}], [11, 27, {"cores": 17, "ethernet": [4, 20], "deadLinks": [0]}], [11, 28, {"cores": 17, "ethernet": [8, 28]}], [11, 29, {"cores": 17, "ethernet": [8, 28]}], [11, 30, {"cores": 17, "ethernet": [8, 28]}], [11, 31, {"cores": 17, "ethernet": [8, 28]}], [11, 32, {"cores": 17, "ethernet": [8, 28]}], [11, 33, {"cores": 17, "ethernet": [8, 28]}], [11, 34, {"cores": 17, "ethernet": [8, 28]}], [11, 35, {"cores": 17, "ethernet": [4, 32], "deadLinks": [1]}], [11, 36, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 37, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 38, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1]}], [11, 39, {"cores": 17, "ethernet": [4, 32], "deadLinks": [0, 1, 2]}], [12, 4, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 4, 5]}], [12, 5, {"cores": 17, "ethernet": [8, 4]}], [12, 6, {"cores": 17, "ethernet": [8, 4]}], [12, 7, {"cores": 17, "ethernet": [8, 4]}], [12, 8, {"cores": 17, "ethernet": [8, 4]}], [12, 9, {"cores": 17, "ethernet": [8, 4]}], [12, 10, {"cores": 17, "ethernet": [8, 4]}], [12, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [12, 16, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 17, {"cores": 17, "ethernet": [8, 16]}], [12, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [2]}], [12, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [12, 20, {"cores": 17, "ethernet": [8, 16]}], [12, 21, {"cores": 17, "ethernet": [8, 16]}], [12, 22, {"cores": 17, "ethernet": [8, 16]}], [12, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [12, 28, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [12, 29, {"cores": 17, "ethernet": [8, 28]}], [12, 30, {"cores": 17, "ethernet": [8, 28]}], [12, 31, {"cores": 17, "ethernet": [8, 28]}], [12, 32, {"cores": 17, "ethernet": [8, 28]}], [12, 33, {"cores": 17, "ethernet": [8, 28]}], [12, 34, {"cores": 17, "ethernet": [8, 28]}], [12, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [13, 5, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [13, 6, {"cores": 17, "ethernet": [8, 4]}], [13, 7, {"cores": 17, "ethernet": [8, 4]}], [13, 8, {"cores": 17, "ethernet": [8, 4]}], [13, 9, {"cores": 17, "ethernet": [8, 4]}], [13, 10, {"cores": 17, "ethernet": [8, 4]}], [13, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [13, 17, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [13, 18, {"cores": 17, "ethernet": [8, 16]}], [13, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [3]}], [13, 20, {"cores": 17, "ethernet": [8, 16]}], [13, 21, {"cores": 17, "ethernet": [8, 16]}], [13, 22, {"cores": 17, "ethernet": [8, 16]}], [13, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [13, 29, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [13, 30, {"cores": 17, "ethernet": [8, 28]}], [13, 31, {"cores": 17, "ethernet": [8, 28]}], [13, 32, {"cores": 17, "ethernet": [8, 28]}], [13, 33, {"cores": 17, "ethernet": [8, 28]}], [13, 34, {"cores": 17, "ethernet": [8, 28]}], [13, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [14, 6, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 5]}], [14, 7, {"cores": 17, "ethernet": [8, 4]}], [14, 8, {"cores": 17, "ethernet": [8, 4]}], [14, 9, {"cores": 17, "ethernet": [8, 4]}], [14, 10, {"cores": 17, "ethernet": [8, 4]}], [14, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [1, 2]}], [14, 18, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 5]}], [14, 19, {"cores": 17, "ethernet": [8, 16]}], [14, 20, {"cores": 17, "ethernet": [8, 16]}], [14, 21, {"cores": 17, "ethernet": [8, 16]}], [14, 22, {"cores": 17, "ethernet": [8, 16]}], [14, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [1, 2]}], [14, 30, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 5]}], [14, 31, {"cores": 17, "ethernet": [8, 28]}], [14, 32, {"cores": 17, "ethernet": [8, 28]}], [14, 33, {"cores": 17, "ethernet": [8, 28]}], [14, 34, {"cores": 17, "ethernet": [8, 28]}], [14, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [1, 2]}], [15, 7, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 5]}], [15, 8, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 9, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 10, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1]}], [15, 11, {"cores": 17, "ethernet": [8, 4], "deadLinks": [0, 1, 2]}], [15, 19, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 5]}], [15, 20, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 21, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 22, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1]}], [15, 23, {"cores": 17, "ethernet": [8, 16], "deadLinks": [0, 1, 2]}], [15, 31, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 5]}], [15, 32, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 33, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 34, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1]}], [15, 35, {"cores": 17, "ethernet": [8, 28], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn2.json b/SpiNNaker-machine/src/test/resources/spinn2.json index 89e2f8bd6d..e2be180d63 100644 --- a/SpiNNaker-machine/src/test/resources/spinn2.json +++ b/SpiNNaker-machine/src/test/resources/spinn2.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.193.148"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0], "deadLinks": [2]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn4.json b/SpiNNaker-machine/src/test/resources/spinn4.json index 0174e20a48..9c8b1a635c 100644 --- a/SpiNNaker-machine/src/test/resources/spinn4.json +++ b/SpiNNaker-machine/src/test/resources/spinn4.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 17, "ethernet": [0, 0]}], [1, 2, {"cores": 18, "ethernet": [0, 0]}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json b/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json index be59185215..2fe28e5652 100644 --- a/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json +++ b/SpiNNaker-machine/src/test/resources/spinn4_fiddle.json @@ -1 +1 @@ -{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 117}, {"monitors": 2, "routerEntries": 2147483647, "sdram": 123469692}], [1, 2, {"cores": 18, "ethernet": [0, 0]}, {"monitors": 3, "sdram": 123469691}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file +{"height": 8, "width": 8, "root": [0, 0], "standardResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": []}, "ethernetResources": {"monitors": 1, "routerEntries": 1023, "sdram": 123469792, "tags": [1, 2, 3, 4, 5, 6, 7]}, "chips": [[0, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4, 5], "ipAddress": "130.88.192.243"}], [0, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [3, 4]}], [0, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3, 4]}], [1, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [1, 1, {"cores": 117}, {"monitors": 2, "routerEntries": 2147483647, "sdram": 123469692}], [1, 2, {"cores": 18, "ethernet": [0, 0]}, {"monitors": 3, "sdram": 123469691}], [1, 3, {"cores": 17, "ethernet": [0, 0]}], [1, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [2, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [2, 1, {"cores": 18, "ethernet": [0, 0]}], [2, 2, {"cores": 18, "ethernet": [0, 0]}], [2, 3, {"cores": 18, "ethernet": [0, 0]}], [2, 4, {"cores": 18, "ethernet": [0, 0]}], [2, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [3, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [4, 5]}], [3, 1, {"cores": 17, "ethernet": [0, 0]}], [3, 2, {"cores": 18, "ethernet": [0, 0]}], [3, 3, {"cores": 17, "ethernet": [0, 0]}], [3, 4, {"cores": 18, "ethernet": [0, 0]}], [3, 5, {"cores": 17, "ethernet": [0, 0]}], [3, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [2, 3]}], [4, 0, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 4, 5]}], [4, 1, {"cores": 18, "ethernet": [0, 0]}], [4, 2, {"cores": 18, "ethernet": [0, 0]}], [4, 3, {"cores": 18, "ethernet": [0, 0]}], [4, 4, {"cores": 18, "ethernet": [0, 0]}], [4, 5, {"cores": 18, "ethernet": [0, 0]}], [4, 6, {"cores": 18, "ethernet": [0, 0]}], [4, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2, 3]}], [5, 1, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [5, 2, {"cores": 17, "ethernet": [0, 0]}], [5, 3, {"cores": 18, "ethernet": [0, 0]}], [5, 4, {"cores": 17, "ethernet": [0, 0]}], [5, 5, {"cores": 18, "ethernet": [0, 0]}], [5, 6, {"cores": 17, "ethernet": [0, 0]}], [5, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [6, 2, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 5]}], [6, 3, {"cores": 18, "ethernet": [0, 0]}], [6, 4, {"cores": 18, "ethernet": [0, 0]}], [6, 5, {"cores": 18, "ethernet": [0, 0]}], [6, 6, {"cores": 18, "ethernet": [0, 0]}], [6, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [1, 2]}], [7, 3, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 5]}], [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-machine/src/test/resources/test24_12.json b/SpiNNaker-machine/src/test/resources/test24_12.json index f15f52d6ca..7b496e9aac 100644 --- a/SpiNNaker-machine/src/test/resources/test24_12.json +++ b/SpiNNaker-machine/src/test/resources/test24_12.json @@ -49,4 +49,4 @@ [7, 4, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 5, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], [7, 6, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1]}], - [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} \ No newline at end of file + [7, 7, {"cores": 18, "ethernet": [0, 0], "deadLinks": [0, 1, 2]}]]} diff --git a/SpiNNaker-pacman/src/test/java/.gitignore b/SpiNNaker-pacman/src/test/java/.gitignore index e69de29bb2..8b13789179 100644 --- a/SpiNNaker-pacman/src/test/java/.gitignore +++ b/SpiNNaker-pacman/src/test/java/.gitignore @@ -0,0 +1 @@ + diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java index 3657f19346..1419ffdd25 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Configuration.java @@ -1,82 +1,82 @@ -/* - * 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 - * - * http://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.py2json; - -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toList; - -import java.util.List; - -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - -import org.python.core.PyObject; - -import uk.ac.manchester.spinnaker.utils.validation.IPAddress; -import uk.ac.manchester.spinnaker.utils.validation.TCPPort; - -/** A configuration description. JSON-serializable. */ -public final class Configuration { - /** The machines to manage. */ - @NotEmpty(message = "there must be at least one machine described") - public final List<@Valid Machine> machines; - - /** The port for the service to listen on. */ - @TCPPort - public final int port; - - /** - * The host address for the service to listen on. Empty = all interfaces. - */ - @IPAddress(emptyOK = true) - public final String ip; - - /** How often (in seconds) to check for timeouts. */ - @Positive - public final double timeoutCheckInterval; - - /** How many retired jobs to retain. */ - @PositiveOrZero - public final int maxRetiredJobs; - - /** Time to wait before freeing. */ - @PositiveOrZero - public final int secondsBeforeFree; - - Configuration(PyObject configuration) { - machines = toList(getattr(configuration, "machines"), Machine::new); - port = getattr(configuration, "port").asInt(); - ip = getattr(configuration, "ip").asString(); - timeoutCheckInterval = - getattr(configuration, "timeout_check_interval").asDouble(); - maxRetiredJobs = getattr(configuration, "max_retired_jobs").asInt(); - secondsBeforeFree = - getattr(configuration, "seconds_before_free").asInt(); - } - - @Override - public String toString() { - return new StringBuilder("Configuration(").append("machines=") - .append(machines).append(",").append("port=").append(port) - .append(",").append("ip=").append(ip).append(",") - .append("timeoutCheckInterval=").append(timeoutCheckInterval) - .append(",").append("maxRetiredJobs=").append(maxRetiredJobs) - .append(",").append("secondsBeforeFree=") - .append(secondsBeforeFree).append(")").toString(); - } -} +/* + * 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 + * + * http://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.py2json; + +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toList; + +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; + +import org.python.core.PyObject; + +import uk.ac.manchester.spinnaker.utils.validation.IPAddress; +import uk.ac.manchester.spinnaker.utils.validation.TCPPort; + +/** A configuration description. JSON-serializable. */ +public final class Configuration { + /** The machines to manage. */ + @NotEmpty(message = "there must be at least one machine described") + public final List<@Valid Machine> machines; + + /** The port for the service to listen on. */ + @TCPPort + public final int port; + + /** + * The host address for the service to listen on. Empty = all interfaces. + */ + @IPAddress(emptyOK = true) + public final String ip; + + /** How often (in seconds) to check for timeouts. */ + @Positive + public final double timeoutCheckInterval; + + /** How many retired jobs to retain. */ + @PositiveOrZero + public final int maxRetiredJobs; + + /** Time to wait before freeing. */ + @PositiveOrZero + public final int secondsBeforeFree; + + Configuration(PyObject configuration) { + machines = toList(getattr(configuration, "machines"), Machine::new); + port = getattr(configuration, "port").asInt(); + ip = getattr(configuration, "ip").asString(); + timeoutCheckInterval = + getattr(configuration, "timeout_check_interval").asDouble(); + maxRetiredJobs = getattr(configuration, "max_retired_jobs").asInt(); + secondsBeforeFree = + getattr(configuration, "seconds_before_free").asInt(); + } + + @Override + public String toString() { + return new StringBuilder("Configuration(").append("machines=") + .append(machines).append(",").append("port=").append(port) + .append(",").append("ip=").append(ip).append(",") + .append("timeoutCheckInterval=").append(timeoutCheckInterval) + .append(",").append("maxRetiredJobs=").append(maxRetiredJobs) + .append(",").append("secondsBeforeFree=") + .append(secondsBeforeFree).append(")").toString(); + } +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java index 60ccc93037..193a014cc6 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Link.java @@ -1,43 +1,43 @@ -/* - * 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 - * - * http://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.py2json; - -/** - * Enumeration of links from a SpiNNaker chip. - *

- * Note that the numbers chosen have two useful properties: - * - *

    - *
  • The integer values assigned are chosen to match the numbers used to - * identify the links in the low-level software API and hardware registers. - *
  • The links are ordered consecutively in anticlockwise order meaning the - * opposite link is {@code (link+3)%6}. - *
- */ -public enum Link { - /** East. */ - east, - /** North-East. */ - northEast, - /** North. */ - north, - /** West. */ - west, - /** South-West. */ - southWest, - /** South. */ - south -} +/* + * 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 + * + * http://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.py2json; + +/** + * Enumeration of links from a SpiNNaker chip. + *

+ * Note that the numbers chosen have two useful properties: + * + *

    + *
  • The integer values assigned are chosen to match the numbers used to + * identify the links in the low-level software API and hardware registers. + *
  • The links are ordered consecutively in anticlockwise order meaning the + * opposite link is {@code (link+3)%6}. + *
+ */ +public enum Link { + /** East. */ + east, + /** North-East. */ + northEast, + /** North. */ + north, + /** West. */ + west, + /** South-West. */ + southWest, + /** South. */ + south +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java index afe8d0aef2..ad7fb35575 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/Machine.java @@ -1,177 +1,177 @@ -/* - * 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 - * - * http://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.py2json; - -import static java.util.Collections.disjoint; -import static java.util.EnumSet.noneOf; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.item; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toCollectingMap; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toMap; -import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toSet; - -import java.util.EnumSet; -import java.util.Map; -import java.util.Set; - -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -import org.python.core.PyObject; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.errorprone.annotations.Keep; - -import uk.ac.manchester.spinnaker.machine.board.BMPCoords; -import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; -import uk.ac.manchester.spinnaker.machine.board.TriadCoords; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadHeight; -import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth; -import uk.ac.manchester.spinnaker.utils.validation.IPAddress; - -/** A machine description. JSON-serializable. */ -public final class Machine { - /** The name of the machine. */ - @NotBlank - public final String name; - - /** The tags of the machine. */ - @NotEmpty - public final Set<@NotBlank String> tags; - - /** The width of the machine, in triads. */ - @ValidTriadWidth - public final int width; - - /** The height of the machine, in triads. */ - @ValidTriadHeight - public final int height; - - /** The dead boards of the machine. */ - public final Set<@Valid TriadCoords> deadBoards; - - /** - * The extra dead links of the machine. Doesn't include links to dead - * boards. - */ - @NotNull - public final Map<@Valid TriadCoords, @NotEmpty EnumSet> deadLinks; - - /** The logical-to-physical board location map. */ - @NotNull - public final Map<@Valid TriadCoords, @Valid PhysicalCoords> boardLocations; - - /** The IP addresses of the BMPs. */ - @JsonProperty("bmp-ips") - @NotNull - public final Map<@Valid BMPCoords, @IPAddress String> bmpIPs; - - /** The IP addresses of the boards. */ - @JsonProperty("spinnaker-ips") - @NotNull - public final Map<@Valid TriadCoords, @IPAddress String> spinnakerIPs; - - private static final int IDX = 3; - - Machine(PyObject machine) { - name = getattr(machine, "name").asString(); - tags = toSet(getattr(machine, "tags"), PyObject::asString); - width = getattr(machine, "width").asInt(); - height = getattr(machine, "height").asInt(); - deadBoards = toSet(getattr(machine, "dead_boards"), Machine::xyz); - deadLinks = toCollectingMap(getattr(machine, "dead_links"), - Machine::xyz, () -> noneOf(Link.class), - key -> Link.values()[item(key, IDX).asInt()]); - boardLocations = toMap(getattr(machine, "board_locations"), - Machine::xyz, Machine::cfb); - bmpIPs = toMap(getattr(machine, "bmp_ips"), Machine::cf, - PyObject::asString); - spinnakerIPs = toMap(getattr(machine, "spinnaker_ips"), Machine::xyz, - PyObject::asString); - } - - private static TriadCoords xyz(PyObject tuple) { - int index = 0; - int x = item(tuple, index++).asInt(); - int y = item(tuple, index++).asInt(); - int z = item(tuple, index++).asInt(); - return new TriadCoords(x, y, z); - } - - private static PhysicalCoords cfb(PyObject tuple) { - int index = 0; - int c = item(tuple, index++).asInt(); - int f = item(tuple, index++).asInt(); - int b = item(tuple, index++).asInt(); - return new PhysicalCoords(c, f, b); - } - - private static BMPCoords cf(PyObject tuple) { - int index = 0; - int c = item(tuple, index++).asInt(); - int f = item(tuple, index++).asInt(); - return new BMPCoords(c, f); - } - - @Override - public String toString() { - return new StringBuilder("Machine(").append("name=").append(name) - .append(",").append("tags=").append(tags).append(",") - .append("width=").append(width).append(",").append("height=") - .append(height).append(",").append("deadBoards=") - .append(deadBoards).append(",").append("deadLinks=") - .append(deadLinks).append(",").append("boardLocations=") - .append(boardLocations).append(",").append("bmpIPs=") - .append(bmpIPs).append(",").append("spinnakerIPs=") - .append(spinnakerIPs).append(")").toString(); - } - - @Keep - @AssertTrue(message = "all boards must have a location and an IP address") - private boolean isEveryBoardWithBMPAndIPaddress() { - return boardLocations.keySet().equals(spinnakerIPs.keySet()); - } - - @Keep - @AssertTrue(message = "every board's IP address must be unique") - private boolean isEveryBoardIPAddressUnique() { - return spinnakerIPs.size() == Set.copyOf(spinnakerIPs.values()).size(); - } - - @Keep - @AssertTrue(message = "every BMP's IP address must be unique") - private boolean isEveryBmpIPAddressUnique() { - return bmpIPs.size() == Set.copyOf(bmpIPs.values()).size(); - } - - @Keep - @AssertTrue(message = "IP addresses may not be assigned to " - + "both boards and BMPs") - private boolean isBoardAddressSetDisjointFromBmpAddressSet() { - return disjoint(spinnakerIPs.values(), bmpIPs.values()); - } - - @Keep - @AssertTrue(message = "every board's BMP must be addressable") - private boolean isEveryBoardManaged() { - return boardLocations.values().stream() - .map(PhysicalCoords::getBmpCoords) - .allMatch(bmpIPs::containsKey); - } -} +/* + * 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 + * + * http://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.py2json; + +import static java.util.Collections.disjoint; +import static java.util.EnumSet.noneOf; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.getattr; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.item; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toCollectingMap; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toMap; +import static uk.ac.manchester.spinnaker.py2json.PythonUtils.toSet; + +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; + +import javax.validation.Valid; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.python.core.PyObject; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.errorprone.annotations.Keep; + +import uk.ac.manchester.spinnaker.machine.board.BMPCoords; +import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords; +import uk.ac.manchester.spinnaker.machine.board.TriadCoords; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadHeight; +import uk.ac.manchester.spinnaker.machine.board.ValidTriadWidth; +import uk.ac.manchester.spinnaker.utils.validation.IPAddress; + +/** A machine description. JSON-serializable. */ +public final class Machine { + /** The name of the machine. */ + @NotBlank + public final String name; + + /** The tags of the machine. */ + @NotEmpty + public final Set<@NotBlank String> tags; + + /** The width of the machine, in triads. */ + @ValidTriadWidth + public final int width; + + /** The height of the machine, in triads. */ + @ValidTriadHeight + public final int height; + + /** The dead boards of the machine. */ + public final Set<@Valid TriadCoords> deadBoards; + + /** + * The extra dead links of the machine. Doesn't include links to dead + * boards. + */ + @NotNull + public final Map<@Valid TriadCoords, @NotEmpty EnumSet> deadLinks; + + /** The logical-to-physical board location map. */ + @NotNull + public final Map<@Valid TriadCoords, @Valid PhysicalCoords> boardLocations; + + /** The IP addresses of the BMPs. */ + @JsonProperty("bmp-ips") + @NotNull + public final Map<@Valid BMPCoords, @IPAddress String> bmpIPs; + + /** The IP addresses of the boards. */ + @JsonProperty("spinnaker-ips") + @NotNull + public final Map<@Valid TriadCoords, @IPAddress String> spinnakerIPs; + + private static final int IDX = 3; + + Machine(PyObject machine) { + name = getattr(machine, "name").asString(); + tags = toSet(getattr(machine, "tags"), PyObject::asString); + width = getattr(machine, "width").asInt(); + height = getattr(machine, "height").asInt(); + deadBoards = toSet(getattr(machine, "dead_boards"), Machine::xyz); + deadLinks = toCollectingMap(getattr(machine, "dead_links"), + Machine::xyz, () -> noneOf(Link.class), + key -> Link.values()[item(key, IDX).asInt()]); + boardLocations = toMap(getattr(machine, "board_locations"), + Machine::xyz, Machine::cfb); + bmpIPs = toMap(getattr(machine, "bmp_ips"), Machine::cf, + PyObject::asString); + spinnakerIPs = toMap(getattr(machine, "spinnaker_ips"), Machine::xyz, + PyObject::asString); + } + + private static TriadCoords xyz(PyObject tuple) { + int index = 0; + int x = item(tuple, index++).asInt(); + int y = item(tuple, index++).asInt(); + int z = item(tuple, index++).asInt(); + return new TriadCoords(x, y, z); + } + + private static PhysicalCoords cfb(PyObject tuple) { + int index = 0; + int c = item(tuple, index++).asInt(); + int f = item(tuple, index++).asInt(); + int b = item(tuple, index++).asInt(); + return new PhysicalCoords(c, f, b); + } + + private static BMPCoords cf(PyObject tuple) { + int index = 0; + int c = item(tuple, index++).asInt(); + int f = item(tuple, index++).asInt(); + return new BMPCoords(c, f); + } + + @Override + public String toString() { + return new StringBuilder("Machine(").append("name=").append(name) + .append(",").append("tags=").append(tags).append(",") + .append("width=").append(width).append(",").append("height=") + .append(height).append(",").append("deadBoards=") + .append(deadBoards).append(",").append("deadLinks=") + .append(deadLinks).append(",").append("boardLocations=") + .append(boardLocations).append(",").append("bmpIPs=") + .append(bmpIPs).append(",").append("spinnakerIPs=") + .append(spinnakerIPs).append(")").toString(); + } + + @Keep + @AssertTrue(message = "all boards must have a location and an IP address") + private boolean isEveryBoardWithBMPAndIPaddress() { + return boardLocations.keySet().equals(spinnakerIPs.keySet()); + } + + @Keep + @AssertTrue(message = "every board's IP address must be unique") + private boolean isEveryBoardIPAddressUnique() { + return spinnakerIPs.size() == Set.copyOf(spinnakerIPs.values()).size(); + } + + @Keep + @AssertTrue(message = "every BMP's IP address must be unique") + private boolean isEveryBmpIPAddressUnique() { + return bmpIPs.size() == Set.copyOf(bmpIPs.values()).size(); + } + + @Keep + @AssertTrue(message = "IP addresses may not be assigned to " + + "both boards and BMPs") + private boolean isBoardAddressSetDisjointFromBmpAddressSet() { + return disjoint(spinnakerIPs.values(), bmpIPs.values()); + } + + @Keep + @AssertTrue(message = "every board's BMP must be addressable") + private boolean isEveryBoardManaged() { + return boardLocations.values().stream() + .map(PhysicalCoords::getBmpCoords) + .allMatch(bmpIPs::containsKey); + } +} diff --git a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java index c1984c35e9..01521ab022 100644 --- a/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java +++ b/SpiNNaker-py2json/src/main/java/uk/ac/manchester/spinnaker/py2json/WithCurrentDirectory.java @@ -1,58 +1,58 @@ -/* - * 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 - * - * http://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.py2json; - -import static java.lang.System.getProperty; - -import java.nio.file.Paths; - -import org.python.core.PySystemState; -import org.python.util.PythonInterpreter; - -import com.google.errorprone.annotations.MustBeClosed; - -/** - * Sets the Jython notion of what the working directory is for the duration of - * the the context. This isn't properly the current working directory (Java code - * really doesn't care!) but it is what the Python side expects. - *

- * @see PySystemState#setCurrentWorkingDir(String) - */ -final class WithCurrentDirectory implements AutoCloseable { - private final PySystemState sys; - - private final String oldCwd; - - @MustBeClosed - WithCurrentDirectory(PythonInterpreter python, boolean doCd) { - if (doCd) { - sys = python.getSystemState(); - oldCwd = sys.getCurrentWorkingDir(); - sys.setCurrentWorkingDir(Paths.get(getProperty("user.dir")) - .toAbsolutePath().toString()); - } else { - sys = null; - oldCwd = null; - } - } - - @Override - public void close() { - if (sys != null) { - sys.setCurrentWorkingDir(oldCwd); - } - } -} +/* + * 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 + * + * http://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.py2json; + +import static java.lang.System.getProperty; + +import java.nio.file.Paths; + +import org.python.core.PySystemState; +import org.python.util.PythonInterpreter; + +import com.google.errorprone.annotations.MustBeClosed; + +/** + * Sets the Jython notion of what the working directory is for the duration of + * the the context. This isn't properly the current working directory (Java code + * really doesn't care!) but it is what the Python side expects. + *

+ * @see PySystemState#setCurrentWorkingDir(String) + */ +final class WithCurrentDirectory implements AutoCloseable { + private final PySystemState sys; + + private final String oldCwd; + + @MustBeClosed + WithCurrentDirectory(PythonInterpreter python, boolean doCd) { + if (doCd) { + sys = python.getSystemState(); + oldCwd = sys.getCurrentWorkingDir(); + sys.setCurrentWorkingDir(Paths.get(getProperty("user.dir")) + .toAbsolutePath().toString()); + } else { + sys = null; + oldCwd = null; + } + } + + @Override + public void close() { + if (sys != null) { + sys.setCurrentWorkingDir(oldCwd); + } + } +} diff --git a/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py b/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py index 8de8ed6768..8030369a6a 100644 --- a/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py +++ b/SpiNNaker-py2json/src/test/resources/uk/ac/manchester/spinnaker/py2json/three_board.py @@ -1,41 +1,41 @@ -# 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 -# -# http://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. - -from spalloc_server.configuration import * -from spalloc_server.links import * - -m = Machine(name="my-three-board-machine", - board_locations={ - #X Y Z C F B - (0, 0, 0): (0, 0, 0), - (0, 0, 1): (0, 0, 2), - (0, 0, 2): (0, 0, 5), - }, - # Just one BMP - bmp_ips={ - #C F - (0, 0): "192.168.240.0", - }, - # Each SpiNNaker board has an IP - spinnaker_ips={ - #X Y Z - (0, 0, 0): "192.168.240.1", - (0, 0, 1): "192.168.240.17", - (0, 0, 2): "192.168.240.41", - }, - dead_links={ - #X Y Z Direction - (0, 0, 0, Links.east) - }) -configuration = Configuration(machines=[m]) +# 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 +# +# http://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. + +from spalloc_server.configuration import * +from spalloc_server.links import * + +m = Machine(name="my-three-board-machine", + board_locations={ + #X Y Z C F B + (0, 0, 0): (0, 0, 0), + (0, 0, 1): (0, 0, 2), + (0, 0, 2): (0, 0, 5), + }, + # Just one BMP + bmp_ips={ + #C F + (0, 0): "192.168.240.0", + }, + # Each SpiNNaker board has an IP + spinnaker_ips={ + #X Y Z + (0, 0, 0): "192.168.240.1", + (0, 0, 1): "192.168.240.17", + (0, 0, 2): "192.168.240.41", + }, + dead_links={ + #X Y Z Direction + (0, 0, 0, Links.east) + }) +configuration = Configuration(machines=[m]) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java index 55d878fe86..3049cc18ee 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/Ordinals.java @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.storage.sqlite; - -/** Ordinal numbers. Used for positional parameters in SQL statements. */ -interface Ordinals { - /** First. */ - int FIRST = 1; - - /** Second. */ - int SECOND = 2; - - /** Third. */ - int THIRD = 3; - - /** Fourth. */ - int FOURTH = 4; - - /** Fifth. */ - int FIFTH = 5; - - /** Sixth. */ - int SIXTH = 6; -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.storage.sqlite; + +/** Ordinal numbers. Used for positional parameters in SQL statements. */ +interface Ordinals { + /** First. */ + int FIRST = 1; + + /** Second. */ + int SECOND = 2; + + /** Third. */ + int THIRD = 3; + + /** Fourth. */ + int FOURTH = 4; + + /** Fifth. */ + int FIFTH = 5; + + /** Sixth. */ + int SIXTH = 6; +} diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java index 767593dafc..810b4dd6c0 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/ResourceLoader.java @@ -1,61 +1,61 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.storage.sqlite; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Objects.isNull; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.commons.io.IOUtils; - -import com.google.errorprone.annotations.MustBeClosed; - -/** - * Factoring out of correct resource loading pattern. - */ -public abstract class ResourceLoader { - private ResourceLoader() { - } - - @MustBeClosed - private static InputStream open(String name) throws FileNotFoundException { - var stream = ResourceLoader.class.getResourceAsStream(name); - if (isNull(stream)) { - throw new FileNotFoundException(name); - } - return stream; - } - - /** - * Load a text resource from the given name using this class's class loader. - * - * @param name - * The name of the resource to load. - * @return The content of the resource. - * @throws RuntimeException - * If things don't work. Shouldn't happen if build is correct. - */ - public static String loadResource(String name) { - try (var stream = open(name)) { - return IOUtils.toString(stream, UTF_8); - } catch (IOException e) { - throw new RuntimeException("failed to read resource", e); - } - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.storage.sqlite; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Objects.isNull; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; + +import com.google.errorprone.annotations.MustBeClosed; + +/** + * Factoring out of correct resource loading pattern. + */ +public abstract class ResourceLoader { + private ResourceLoader() { + } + + @MustBeClosed + private static InputStream open(String name) throws FileNotFoundException { + var stream = ResourceLoader.class.getResourceAsStream(name); + if (isNull(stream)) { + throw new FileNotFoundException(name); + } + return stream; + } + + /** + * Load a text resource from the given name using this class's class loader. + * + * @param name + * The name of the resource to load. + * @return The content of the resource. + * @throws RuntimeException + * If things don't work. Shouldn't happen if build is correct. + */ + public static String loadResource(String name) { + try (var stream = open(name)) { + return IOUtils.toString(stream, UTF_8); + } catch (IOException e) { + throw new RuntimeException("failed to read resource", e); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java index 7fd0167c64..f3003cd64f 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java @@ -1,128 +1,128 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.Math.min; -import static java.nio.ByteOrder.LITTLE_ENDIAN; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Iterator; - -/** Utility methods for {@link ByteBuffer}s. */ -public abstract class ByteBufferUtils { - private ByteBufferUtils() { - } - - /** - * Make a slice of a byte buffer without modifying the original buffer. - * - * @param src - * The originating buffer. - * @param from - * The offset into the originating buffer where the slice starts. - * @param len - * The length of the slice. - * @return The little-endian slice. This will be read-only if and only if - * the original buffer is read-only. - * @deprecated Replace with - * {@code src.slice(from, len).order(LITTLE_ENDIAN)} - */ - @Deprecated(forRemoval = true) - public static ByteBuffer slice(ByteBuffer src, int from, int len) { - return src.slice(from, len).order(LITTLE_ENDIAN); - } - - /** - * Make a slice of a byte buffer if it exceeds a given size. - * - * @param src - * The originating buffer. - * @param maxSize - * The maximum size of the resulting buffer. - * @return The original buffer or a little-endian slice. This will be - * read-only if and only if the original buffer is read-only. - */ - public static ByteBuffer limitSlice(ByteBuffer src, int maxSize) { - if (src.remaining() <= maxSize) { - return src; - } - return src.slice().order(LITTLE_ENDIAN).limit(maxSize); - } - - /** - * Slice up a buffer buffer into a sequence of (little-endian) byte buffers - * with a maximum size. - * - * @param src - * The buffer to slice up. - * @param chunkSize - * Max size of each chunk. Must be positive. - * @return An iterable of little-endian chunks. Only the final chunk will be - * smaller than the requested chunk size. - */ - public static MappableIterable sliceUp(ByteBuffer src, - int chunkSize) { - return () -> new Iterator<>() { - final ByteBuffer b = src.duplicate(); - - @Override - public boolean hasNext() { - return b.hasRemaining(); - } - - @Override - public ByteBuffer next() { - var s = b.slice(); - s.limit(min(chunkSize, s.limit())); - b.position(b.position() + s.limit()); - return s.order(LITTLE_ENDIAN); - } - }; - } - - /** - * Read a chunk of an input stream into a byte buffer. - * - * @param data - * Where to read from. - * @param workingBuffer - * The buffer to use. The number of bytes remaining in the buffer - * is the maximum number of bytes to read unless the - * maximum bytes remaining is smaller. - * @param maxRemaining - * The maximum number of bytes remaining in the input stream; - * bytes after that point won't be read even if they exist. - * @return A view on the buffer with the data in it (endianness undefined), - * or {@code null} if EOF or the limit is reached. - * @throws IOException - * If reading fails. - */ - public static ByteBuffer read(InputStream data, ByteBuffer workingBuffer, - int maxRemaining) throws IOException { - var tmp = workingBuffer.duplicate(); - int size = min(tmp.remaining(), maxRemaining); - if (size <= 0) { - return null; - } - size = data.read(tmp.array(), tmp.arrayOffset(), size); - if (size <= 0) { - return null; - } - return tmp.limit(size); - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.Math.min; +import static java.nio.ByteOrder.LITTLE_ENDIAN; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Iterator; + +/** Utility methods for {@link ByteBuffer}s. */ +public abstract class ByteBufferUtils { + private ByteBufferUtils() { + } + + /** + * Make a slice of a byte buffer without modifying the original buffer. + * + * @param src + * The originating buffer. + * @param from + * The offset into the originating buffer where the slice starts. + * @param len + * The length of the slice. + * @return The little-endian slice. This will be read-only if and only if + * the original buffer is read-only. + * @deprecated Replace with + * {@code src.slice(from, len).order(LITTLE_ENDIAN)} + */ + @Deprecated(forRemoval = true) + public static ByteBuffer slice(ByteBuffer src, int from, int len) { + return src.slice(from, len).order(LITTLE_ENDIAN); + } + + /** + * Make a slice of a byte buffer if it exceeds a given size. + * + * @param src + * The originating buffer. + * @param maxSize + * The maximum size of the resulting buffer. + * @return The original buffer or a little-endian slice. This will be + * read-only if and only if the original buffer is read-only. + */ + public static ByteBuffer limitSlice(ByteBuffer src, int maxSize) { + if (src.remaining() <= maxSize) { + return src; + } + return src.slice().order(LITTLE_ENDIAN).limit(maxSize); + } + + /** + * Slice up a buffer buffer into a sequence of (little-endian) byte buffers + * with a maximum size. + * + * @param src + * The buffer to slice up. + * @param chunkSize + * Max size of each chunk. Must be positive. + * @return An iterable of little-endian chunks. Only the final chunk will be + * smaller than the requested chunk size. + */ + public static MappableIterable sliceUp(ByteBuffer src, + int chunkSize) { + return () -> new Iterator<>() { + final ByteBuffer b = src.duplicate(); + + @Override + public boolean hasNext() { + return b.hasRemaining(); + } + + @Override + public ByteBuffer next() { + var s = b.slice(); + s.limit(min(chunkSize, s.limit())); + b.position(b.position() + s.limit()); + return s.order(LITTLE_ENDIAN); + } + }; + } + + /** + * Read a chunk of an input stream into a byte buffer. + * + * @param data + * Where to read from. + * @param workingBuffer + * The buffer to use. The number of bytes remaining in the buffer + * is the maximum number of bytes to read unless the + * maximum bytes remaining is smaller. + * @param maxRemaining + * The maximum number of bytes remaining in the input stream; + * bytes after that point won't be read even if they exist. + * @return A view on the buffer with the data in it (endianness undefined), + * or {@code null} if EOF or the limit is reached. + * @throws IOException + * If reading fails. + */ + public static ByteBuffer read(InputStream data, ByteBuffer workingBuffer, + int maxRemaining) throws IOException { + var tmp = workingBuffer.duplicate(); + int size = min(tmp.remaining(), maxRemaining); + if (size <= 0) { + return null; + } + size = data.read(tmp.array(), tmp.arrayOffset(), size); + if (size <= 0) { + return null; + } + return tmp.limit(size); + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java index c917fb2b1c..cc338eb452 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java @@ -1,293 +1,293 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.Math.min; -import static java.util.Arrays.stream; -import static java.util.Collections.unmodifiableCollection; -import static java.util.Collections.unmodifiableList; -import static java.util.Collections.unmodifiableMap; -import static java.util.Collections.unmodifiableSet; -import static java.util.EnumSet.noneOf; -import static java.util.Objects.isNull; -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toUnmodifiableList; -import static java.util.stream.Collectors.toUnmodifiableMap; -import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.IntBinaryOperator; -import java.util.function.IntFunction; -import java.util.function.Supplier; -import java.util.stream.Collector; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * Utilities for working with collections. Things that it would be nice if they - * were in Java itself, but which aren't. - * - * @author Donal Fellows - * @see MappableIterable - */ -public abstract class CollectionUtils { - private CollectionUtils() { - } - - /** - * The binary and operator ({@code &}) as a function. - */ - public static final IntBinaryOperator AND = (a, b) -> a & b; - - /** - * The binary or operator ({@code |}) as a function. - */ - public static final IntBinaryOperator OR = (a, b) -> a | b; - - /** - * Create a collector that collects to an {@link EnumSet}. - * - * @param - * The type of {@code enum} we are collecting. - * @param cls - * The class of the {@code enum} we are collecting. - * @return The collector. - */ - public static > Collector> toEnumSet( - Class cls) { - return toCollection(() -> noneOf(cls)); - } - - /** - * Generate an iterable that covers a range. Only expected to cover the - * range once. - * - * @param startAt - * What value to start at. - * @param upTo - * What value to go up to (in steps of +1) but not include. - * @return A one-shot iterable. - */ - public static Iterable range(int startAt, int upTo) { - return IntStream.range(startAt, upTo)::iterator; - } - - /** - * Generate an iterable that covers a range starting at zero and counting - * up. Only expected to cover the range once. - * - * @param upTo - * What value to go up to (in steps of +1) but not include. - * @return A one-shot iterable. - */ - public static Iterable range(int upTo) { - return IntStream.range(0, upTo)::iterator; - } - - /** - * Binary function currier. - * - * @param - * First argument type. - * @param - * Second argument type - * @param - * Return type. - * @param fn - * Binary function. - * @param arg - * First argument. - * @return Unary function based on binding the first argument to the binary - * function. - */ - public static Function curry(BiFunction fn, - T arg) { - return u -> fn.apply(arg, u); - } - - /** - * Given a list of elements, split it into batches of elements of a given - * size. The final batch might be smaller. Note that this requires - * a list because it uses the {@link List#subList(int, int)} method. - * - * @param - * The type of the elements of the input list. - * @param batchSize - * The maximum number of elements in a batch. All but the final - * batch will have this number of elements; the final batch may - * have fewer. - * @param input - * The list to be split into batches. - * @return The batched list. The collections that make up each batch will be - * unmodifiable, as will the overall collection. - */ - public static Collection> batch(int batchSize, - List input) { - return IntStream.range(0, ceildiv(input.size(), batchSize)) - .map(i -> i * batchSize) - .mapToObj(idx -> unmodifiableCollection( - input.subList(idx, min(input.size(), idx + batchSize)))) - .collect(toUnmodifiableList()); - } - - /** - * Like {@link Stream#map(Function)}, but for lists/collections. - * - * @param - * The type of elements of the input list. - * @param - * The type of elements of the output list. - * @param list - * The input list. - * @param fun - * How to map an element. - * @return The output list. Unmodifiable. - */ - @UsedInJavadocOnly(Stream.class) - public static List lmap(Collection list, Function fun) { - return list.stream().map(fun).collect(toUnmodifiableList()); - } - - /** - * Utility for making the backing maps for fast {@code enum}s. These are - * expected to be used mainly to invert the trivial mapping from an - * enumeration member to its {@code value} field, though this is not assumed - * by this code. - * - * @param - * The type of the {@code enum}. - * @param - * The type of the value to use as the map key. - * @param enumMembers - * The values in the {@code enum}, as returned by the - * {@code values()} method. - * @param valueExtractor - * How to get the value to use as the map key. - * @return Unmodifiable map from the values to the {@code enum} members. - */ - public static , K> Map makeEnumBackingMap( - E[] enumMembers, Function valueExtractor) { - return stream(enumMembers) - .collect(toUnmodifiableMap(valueExtractor, v -> v)); - } - - /** - * Makes a read-only copy of a list. - * - * @param - * The type of elements in the list. - * @param list - * The list to copy. {@code null} becomes an empty list. - * @return A read-only copy of the list. - */ - public static List copy(List list) { - // Don't copyOf; avoid nullability failures - return isNull(list) ? List.of() - : unmodifiableList(new ArrayList<>(list)); - } - - /** - * Makes a read-only copy of a set. This will preserve whatever order was in - * the input set. - * - * @param - * The type of elements in the set. - * @param set - * The set to copy. {@code null} becomes an empty set. - * @return A read-only copy of the set. - */ - public static Set copy(Set set) { - // Don't copyOf; avoid nullability failures - return isNull(set) ? Set.of() - : unmodifiableSet(new LinkedHashSet<>(set)); - } - - /** - * Makes a read-only copy of a map. This will preserve whatever order was in - * the input map. - * - * @param - * The type of keys in the map. - * @param - * The type of values in the map. - * @param map - * The map to copy. {@code null} becomes an empty map. - * @return A read-only copy of the map. - */ - public static Map copy(Map map) { - // Don't copyOf; avoid nullability failures - return isNull(map) ? Map.of() - : unmodifiableMap(new LinkedHashMap<>(map)); - } - - /** - * Create a collector that produces an array from a stream. The order of the - * elements in the array will be the inherent order of the elements in the - * stream. - * - * @param - * The type of the elements. - * @param generator - * How to make the array. Typically something like - * {@code T[]::new}. - * @return A collector. - */ - public static < - T> Collector collectToArray(IntFunction generator) { - return new Collector, T[]>() { - @Override - public Supplier> supplier() { - return ArrayList::new; - } - - @Override - public BiConsumer, T> accumulator() { - return List::add; - } - - @Override - public BinaryOperator> combiner() { - return (left, right) -> { - left.addAll(right); - return left; - }; - } - - @Override - public Function, T[]> finisher() { - // We know the size right now; use it! - // Also, we assume that the generator is non-crazy - return l -> l.toArray(generator.apply(l.size())); - } - - @Override - public Set characteristics() { - return Set.of(); - } - }; - } -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.Math.min; +import static java.util.Arrays.stream; +import static java.util.Collections.unmodifiableCollection; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.EnumSet.noneOf; +import static java.util.Objects.isNull; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toUnmodifiableList; +import static java.util.stream.Collectors.toUnmodifiableMap; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntFunction; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +/** + * Utilities for working with collections. Things that it would be nice if they + * were in Java itself, but which aren't. + * + * @author Donal Fellows + * @see MappableIterable + */ +public abstract class CollectionUtils { + private CollectionUtils() { + } + + /** + * The binary and operator ({@code &}) as a function. + */ + public static final IntBinaryOperator AND = (a, b) -> a & b; + + /** + * The binary or operator ({@code |}) as a function. + */ + public static final IntBinaryOperator OR = (a, b) -> a | b; + + /** + * Create a collector that collects to an {@link EnumSet}. + * + * @param + * The type of {@code enum} we are collecting. + * @param cls + * The class of the {@code enum} we are collecting. + * @return The collector. + */ + public static > Collector> toEnumSet( + Class cls) { + return toCollection(() -> noneOf(cls)); + } + + /** + * Generate an iterable that covers a range. Only expected to cover the + * range once. + * + * @param startAt + * What value to start at. + * @param upTo + * What value to go up to (in steps of +1) but not include. + * @return A one-shot iterable. + */ + public static Iterable range(int startAt, int upTo) { + return IntStream.range(startAt, upTo)::iterator; + } + + /** + * Generate an iterable that covers a range starting at zero and counting + * up. Only expected to cover the range once. + * + * @param upTo + * What value to go up to (in steps of +1) but not include. + * @return A one-shot iterable. + */ + public static Iterable range(int upTo) { + return IntStream.range(0, upTo)::iterator; + } + + /** + * Binary function currier. + * + * @param + * First argument type. + * @param + * Second argument type + * @param + * Return type. + * @param fn + * Binary function. + * @param arg + * First argument. + * @return Unary function based on binding the first argument to the binary + * function. + */ + public static Function curry(BiFunction fn, + T arg) { + return u -> fn.apply(arg, u); + } + + /** + * Given a list of elements, split it into batches of elements of a given + * size. The final batch might be smaller. Note that this requires + * a list because it uses the {@link List#subList(int, int)} method. + * + * @param + * The type of the elements of the input list. + * @param batchSize + * The maximum number of elements in a batch. All but the final + * batch will have this number of elements; the final batch may + * have fewer. + * @param input + * The list to be split into batches. + * @return The batched list. The collections that make up each batch will be + * unmodifiable, as will the overall collection. + */ + public static Collection> batch(int batchSize, + List input) { + return IntStream.range(0, ceildiv(input.size(), batchSize)) + .map(i -> i * batchSize) + .mapToObj(idx -> unmodifiableCollection( + input.subList(idx, min(input.size(), idx + batchSize)))) + .collect(toUnmodifiableList()); + } + + /** + * Like {@link Stream#map(Function)}, but for lists/collections. + * + * @param + * The type of elements of the input list. + * @param + * The type of elements of the output list. + * @param list + * The input list. + * @param fun + * How to map an element. + * @return The output list. Unmodifiable. + */ + @UsedInJavadocOnly(Stream.class) + public static List lmap(Collection list, Function fun) { + return list.stream().map(fun).collect(toUnmodifiableList()); + } + + /** + * Utility for making the backing maps for fast {@code enum}s. These are + * expected to be used mainly to invert the trivial mapping from an + * enumeration member to its {@code value} field, though this is not assumed + * by this code. + * + * @param + * The type of the {@code enum}. + * @param + * The type of the value to use as the map key. + * @param enumMembers + * The values in the {@code enum}, as returned by the + * {@code values()} method. + * @param valueExtractor + * How to get the value to use as the map key. + * @return Unmodifiable map from the values to the {@code enum} members. + */ + public static , K> Map makeEnumBackingMap( + E[] enumMembers, Function valueExtractor) { + return stream(enumMembers) + .collect(toUnmodifiableMap(valueExtractor, v -> v)); + } + + /** + * Makes a read-only copy of a list. + * + * @param + * The type of elements in the list. + * @param list + * The list to copy. {@code null} becomes an empty list. + * @return A read-only copy of the list. + */ + public static List copy(List list) { + // Don't copyOf; avoid nullability failures + return isNull(list) ? List.of() + : unmodifiableList(new ArrayList<>(list)); + } + + /** + * Makes a read-only copy of a set. This will preserve whatever order was in + * the input set. + * + * @param + * The type of elements in the set. + * @param set + * The set to copy. {@code null} becomes an empty set. + * @return A read-only copy of the set. + */ + public static Set copy(Set set) { + // Don't copyOf; avoid nullability failures + return isNull(set) ? Set.of() + : unmodifiableSet(new LinkedHashSet<>(set)); + } + + /** + * Makes a read-only copy of a map. This will preserve whatever order was in + * the input map. + * + * @param + * The type of keys in the map. + * @param + * The type of values in the map. + * @param map + * The map to copy. {@code null} becomes an empty map. + * @return A read-only copy of the map. + */ + public static Map copy(Map map) { + // Don't copyOf; avoid nullability failures + return isNull(map) ? Map.of() + : unmodifiableMap(new LinkedHashMap<>(map)); + } + + /** + * Create a collector that produces an array from a stream. The order of the + * elements in the array will be the inherent order of the elements in the + * stream. + * + * @param + * The type of the elements. + * @param generator + * How to make the array. Typically something like + * {@code T[]::new}. + * @return A collector. + */ + public static < + T> Collector collectToArray(IntFunction generator) { + return new Collector, T[]>() { + @Override + public Supplier> supplier() { + return ArrayList::new; + } + + @Override + public BiConsumer, T> accumulator() { + return List::add; + } + + @Override + public BinaryOperator> combiner() { + return (left, right) -> { + left.addAll(right); + return left; + }; + } + + @Override + public Function, T[]> finisher() { + // We know the size right now; use it! + // Also, we assume that the generator is non-crazy + return l -> l.toArray(generator.apply(l.size())); + } + + @Override + public Set characteristics() { + return Set.of(); + } + }; + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java index 4583c80b51..de447f27ce 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/Daemon.java @@ -1,83 +1,83 @@ -/* - * Copyright (c) 2018-2022 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 - * - * http://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.utils; - -import static java.util.Objects.requireNonNull; - -/** - * A thread that is a daemon by default. - * - * @author Donal Fellows - */ -public class Daemon extends Thread { - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - */ - public Daemon(Runnable target) { - super(requireNonNull(target)); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - * @param name - * the name of the new thread - */ - public Daemon(Runnable target, String name) { - super(requireNonNull(target), name); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param group - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. - * @param target - * the object whose {@code run} method is invoked when this - * thread is started. Never {@code null}. - */ - public Daemon(ThreadGroup group, Runnable target) { - super(group, requireNonNull(target)); - setDaemon(true); - } - - /** - * Allocate a new daemon thread. This thread is not running. - * - * @param group - * the thread group. If {@code null}, the group is set to the - * current thread's thread group. - * @param target - * the object whose {@link Runnable#run() run} method is invoked - * when this thread is started. Never {@code null}. - * @param name - * the name of the new thread - */ - public Daemon(ThreadGroup group, Runnable target, String name) { - super(group, requireNonNull(target), name); - setDaemon(true); - } -} +/* + * Copyright (c) 2018-2022 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 + * + * http://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.utils; + +import static java.util.Objects.requireNonNull; + +/** + * A thread that is a daemon by default. + * + * @author Donal Fellows + */ +public class Daemon extends Thread { + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + */ + public Daemon(Runnable target) { + super(requireNonNull(target)); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + * @param name + * the name of the new thread + */ + public Daemon(Runnable target, String name) { + super(requireNonNull(target), name); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param group + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. + * @param target + * the object whose {@code run} method is invoked when this + * thread is started. Never {@code null}. + */ + public Daemon(ThreadGroup group, Runnable target) { + super(group, requireNonNull(target)); + setDaemon(true); + } + + /** + * Allocate a new daemon thread. This thread is not running. + * + * @param group + * the thread group. If {@code null}, the group is set to the + * current thread's thread group. + * @param target + * the object whose {@link Runnable#run() run} method is invoked + * when this thread is started. Never {@code null}. + * @param name + * the name of the new thread + */ + public Daemon(ThreadGroup group, Runnable target, String name) { + super(group, requireNonNull(target), name); + setDaemon(true); + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java index b1f167ab87..09249313c8 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/UsedInJavadocOnly.java @@ -1,44 +1,44 @@ -/* - * Copyright (c) 2022 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 - * - * http://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.utils; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -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 the given class is used for Javadoc generation only, but needs to - * be referenced for Checkstyle. With this, the classes in question are - * genuinely used, but only at the source level; no runtime code is generated. - * - * @author Donal Fellows - */ -@Retention(SOURCE) -@Target({ TYPE, METHOD, CONSTRUCTOR, FIELD }) -public @interface UsedInJavadocOnly { - /** - * Class or classes just used by the annotated thing in Javadoc generation. - * Put in with this so Checkstyle doesn't think the class is unused. - * - * @return classes - */ - Class[] value(); -} +/* + * Copyright (c) 2022 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 + * + * http://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.utils; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +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 the given class is used for Javadoc generation only, but needs to + * be referenced for Checkstyle. With this, the classes in question are + * genuinely used, but only at the source level; no runtime code is generated. + * + * @author Donal Fellows + */ +@Retention(SOURCE) +@Target({ TYPE, METHOD, CONSTRUCTOR, FIELD }) +public @interface UsedInJavadocOnly { + /** + * Class or classes just used by the annotated thing in Javadoc generation. + * Put in with this so Checkstyle doesn't think the class is unused. + * + * @return classes + */ + Class[] value(); +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java index b8b3de737c..79c3dfe517 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/TCPPort.java @@ -1,126 +1,126 @@ -/* - * 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 - * - * http://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.utils.validation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -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; - -/** - * Validates that a number looks like a TCP port. Always accepts {@code null}. - * - * @author Donal Fellows - * @see UDPPort - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = TCPPort.Validator.class) -public @interface TCPPort { - /** The minimum ordinary TCP port number. */ - int MIN_TCP_PORT = 1024; - - /** The maximum TCP port number. */ - int MAX_TCP_PORT = 65535; - - /** - * Whether to allow the "any" port. Note that this is not the same as - * allowing any other port; it's more that it isn't bound to a specific - * port. - * - * @return Whether 0 is allowed. - */ - boolean any() default false; - - /** - * Whether to allow system ports. - * - * @return Whether 1-1023 is allowed. - */ - boolean system() default false; - - /** - * Whether to allow ephemeral ports. - * - * @return Whether 32768-65535 is allowed - */ - boolean ephemeral() default true; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad TCP port"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; - - /** - * Validator for {@link TCPPort} constraints. Not intended for direct use. - */ - class Validator implements ConstraintValidator { - private static final int MAX_STD_PORT = 32767; - - private boolean acceptZero; - - private int min; - - private int max; - - @Override - public void initialize(TCPPort annotation) { - acceptZero = annotation.any(); - min = annotation.system() ? 1 : TCPPort.MIN_TCP_PORT; - max = annotation.ephemeral() ? TCPPort.MAX_TCP_PORT : MAX_STD_PORT; - } - - @Override - public boolean isValid(Integer value, - ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - if (value == 0) { - return acceptZero; - } - return (value >= min) && (value <= max); - } - } -} +/* + * 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 + * + * http://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.utils.validation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +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; + +/** + * Validates that a number looks like a TCP port. Always accepts {@code null}. + * + * @author Donal Fellows + * @see UDPPort + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = TCPPort.Validator.class) +public @interface TCPPort { + /** The minimum ordinary TCP port number. */ + int MIN_TCP_PORT = 1024; + + /** The maximum TCP port number. */ + int MAX_TCP_PORT = 65535; + + /** + * Whether to allow the "any" port. Note that this is not the same as + * allowing any other port; it's more that it isn't bound to a specific + * port. + * + * @return Whether 0 is allowed. + */ + boolean any() default false; + + /** + * Whether to allow system ports. + * + * @return Whether 1-1023 is allowed. + */ + boolean system() default false; + + /** + * Whether to allow ephemeral ports. + * + * @return Whether 32768-65535 is allowed + */ + boolean ephemeral() default true; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad TCP port"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; + + /** + * Validator for {@link TCPPort} constraints. Not intended for direct use. + */ + class Validator implements ConstraintValidator { + private static final int MAX_STD_PORT = 32767; + + private boolean acceptZero; + + private int min; + + private int max; + + @Override + public void initialize(TCPPort annotation) { + acceptZero = annotation.any(); + min = annotation.system() ? 1 : TCPPort.MIN_TCP_PORT; + max = annotation.ephemeral() ? TCPPort.MAX_TCP_PORT : MAX_STD_PORT; + } + + @Override + public boolean isValid(Integer value, + ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + if (value == 0) { + return acceptZero; + } + return (value >= min) && (value <= max); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java index 9e30e155ed..540979caf6 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/UDPPort.java @@ -1,125 +1,125 @@ -/* - * 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 - * - * http://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.utils.validation; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.util.Objects.isNull; - -import java.lang.annotation.Documented; -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; - -/** - * Validates that a number looks like a UDP port. Always accepts {@code null}. - * - * @author Donal Fellows - */ -@Documented -@Retention(RUNTIME) -@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) -@Constraint(validatedBy = UDPPort.Validator.class) -public @interface UDPPort { - /** The minimum ordinary UDP port number. */ - int MIN_UDP_PORT = 1024; - - /** The maximum UDP port number. */ - int MAX_UDP_PORT = 65535; - - /** - * Whether to allow the "any" port. Note that this is not the same as - * allowing any other port; it's more that it isn't bound to a specific - * port. - * - * @return Whether 0 is allowed. - */ - boolean any() default false; - - /** - * Whether to allow system ports. - * - * @return Whether 1-1023 is allowed. - */ - boolean system() default false; - - /** - * Whether to allow ephemeral ports. - * - * @return Whether 32768-65535 is allowed - */ - boolean ephemeral() default true; - - /** - * Message on constraint violated. - * - * @return Message - */ - String message() default "${validatedValue} is a bad UDP port"; - - /** - * Group of constraints. Required by validation spec. - * - * @return Constraint groups, if any - */ - Class[] groups() default {}; - - /** - * Payload info. Required by validation spec. - * - * @return Payloads, if any. - */ - Class[] payload() default {}; - - /** - * Validator for {@link UDPPort} constraints. Not intended for direct use. - */ - class Validator implements ConstraintValidator { - private static final int MAX_STD_PORT = 32767; - - private boolean acceptZero; - - private int min; - - private int max; - - @Override - public void initialize(UDPPort annotation) { - acceptZero = annotation.any(); - min = annotation.system() ? 1 : UDPPort.MIN_UDP_PORT; - max = annotation.ephemeral() ? UDPPort.MAX_UDP_PORT : MAX_STD_PORT; - } - - @Override - public boolean isValid(Integer value, - ConstraintValidatorContext context) { - if (isNull(value)) { - return true; - } - if (value == 0) { - return acceptZero; - } - return (value >= min) && (value <= max); - } - } -} +/* + * 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 + * + * http://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.utils.validation; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.isNull; + +import java.lang.annotation.Documented; +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; + +/** + * Validates that a number looks like a UDP port. Always accepts {@code null}. + * + * @author Donal Fellows + */ +@Documented +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE_USE }) +@Constraint(validatedBy = UDPPort.Validator.class) +public @interface UDPPort { + /** The minimum ordinary UDP port number. */ + int MIN_UDP_PORT = 1024; + + /** The maximum UDP port number. */ + int MAX_UDP_PORT = 65535; + + /** + * Whether to allow the "any" port. Note that this is not the same as + * allowing any other port; it's more that it isn't bound to a specific + * port. + * + * @return Whether 0 is allowed. + */ + boolean any() default false; + + /** + * Whether to allow system ports. + * + * @return Whether 1-1023 is allowed. + */ + boolean system() default false; + + /** + * Whether to allow ephemeral ports. + * + * @return Whether 32768-65535 is allowed + */ + boolean ephemeral() default true; + + /** + * Message on constraint violated. + * + * @return Message + */ + String message() default "${validatedValue} is a bad UDP port"; + + /** + * Group of constraints. Required by validation spec. + * + * @return Constraint groups, if any + */ + Class[] groups() default {}; + + /** + * Payload info. Required by validation spec. + * + * @return Payloads, if any. + */ + Class[] payload() default {}; + + /** + * Validator for {@link UDPPort} constraints. Not intended for direct use. + */ + class Validator implements ConstraintValidator { + private static final int MAX_STD_PORT = 32767; + + private boolean acceptZero; + + private int min; + + private int max; + + @Override + public void initialize(UDPPort annotation) { + acceptZero = annotation.any(); + min = annotation.system() ? 1 : UDPPort.MIN_UDP_PORT; + max = annotation.ephemeral() ? UDPPort.MAX_UDP_PORT : MAX_STD_PORT; + } + + @Override + public boolean isValid(Integer value, + ConstraintValidatorContext context) { + if (isNull(value)) { + return true; + } + if (value == 0) { + return acceptZero; + } + return (value >= min) && (value <= max); + } + } +} diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java index 607a29d49c..461b0c7059 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/validation/package-info.java @@ -1,19 +1,19 @@ -/* - * 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 - * - * http://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. - */ -/** - * Utilities for validation of things. - */ -package uk.ac.manchester.spinnaker.utils.validation; +/* + * 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 + * + * http://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. + */ +/** + * Utilities for validation of things. + */ +package uk.ac.manchester.spinnaker.utils.validation; diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java index e7310c1276..312af036ff 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestOneShotEvent.java @@ -1,129 +1,129 @@ -/* - * 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 - * - * http://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.utils; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -/** - * - * @author Christian - */ -public class TestOneShotEvent { - private static void sleep(int ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - System.err.println("unexpected wake from sleep"); - } - } - - public TestOneShotEvent() { - } - - private Runnable hanger = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.await(); - event.fire(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private Runnable inOrder = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.fire(); - event.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private Runnable firer = new Runnable() { - @Override - public void run() { - var event = new OneShotEvent(); - event.fire(); - } - }; - - private Runnable multiple = new Runnable() { - @Override - public void run() { - try { - var event = new OneShotEvent(); - event.fire(); - event.fire(); - event.await(); - event.await(); - event.fire(); - event.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - private OneShotEvent event1 = new OneShotEvent(); - - private Runnable waiter = new Runnable() { - @Override - public void run() { - try { - event1.await(); - } catch (InterruptedException ex) { - // Do nothing should be required; - } - } - }; - - @Test - public void testMultiple() { - var thanger = new Thread(hanger); - thanger.start(); - var tinOrder = new Thread(inOrder); - tinOrder.start(); - var tfirer = new Thread(firer); - tfirer.start(); - var tmultiple = new Thread(multiple); - tmultiple.start(); - var twaiter = new Thread(waiter); - twaiter.start(); - - sleep(500); - - assertTrue(thanger.isAlive()); - thanger.interrupt(); - assertTrue(!tinOrder.isAlive()); - assertTrue(!tfirer.isAlive()); - assertTrue(!tmultiple.isAlive()); - assertTrue(twaiter.isAlive()); - event1.fire(); - - sleep(50); - - assertTrue(!twaiter.isAlive()); - } - -} +/* + * 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 + * + * http://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.utils; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * + * @author Christian + */ +public class TestOneShotEvent { + private static void sleep(int ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.err.println("unexpected wake from sleep"); + } + } + + public TestOneShotEvent() { + } + + private Runnable hanger = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.await(); + event.fire(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private Runnable inOrder = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.fire(); + event.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private Runnable firer = new Runnable() { + @Override + public void run() { + var event = new OneShotEvent(); + event.fire(); + } + }; + + private Runnable multiple = new Runnable() { + @Override + public void run() { + try { + var event = new OneShotEvent(); + event.fire(); + event.fire(); + event.await(); + event.await(); + event.fire(); + event.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + private OneShotEvent event1 = new OneShotEvent(); + + private Runnable waiter = new Runnable() { + @Override + public void run() { + try { + event1.await(); + } catch (InterruptedException ex) { + // Do nothing should be required; + } + } + }; + + @Test + public void testMultiple() { + var thanger = new Thread(hanger); + thanger.start(); + var tinOrder = new Thread(inOrder); + tinOrder.start(); + var tfirer = new Thread(firer); + tfirer.start(); + var tmultiple = new Thread(multiple); + tmultiple.start(); + var twaiter = new Thread(waiter); + twaiter.start(); + + sleep(500); + + assertTrue(thanger.isAlive()); + thanger.interrupt(); + assertTrue(!tinOrder.isAlive()); + assertTrue(!tfirer.isAlive()); + assertTrue(!tmultiple.isAlive()); + assertTrue(twaiter.isAlive()); + event1.fire(); + + sleep(50); + + assertTrue(!twaiter.isAlive()); + } + +} diff --git a/src/support/javadoc/com.fasterxml.jackson.core/package-list b/src/support/javadoc/com.fasterxml.jackson.core/package-list index bb8a79efb8..87b90659df 100644 --- a/src/support/javadoc/com.fasterxml.jackson.core/package-list +++ b/src/support/javadoc/com.fasterxml.jackson.core/package-list @@ -1,14 +1,14 @@ -com.fasterxml.jackson.core -com.fasterxml.jackson.core.async -com.fasterxml.jackson.core.base -com.fasterxml.jackson.core.exc -com.fasterxml.jackson.core.filter -com.fasterxml.jackson.core.format -com.fasterxml.jackson.core.io -com.fasterxml.jackson.core.io.doubleparser -com.fasterxml.jackson.core.io.schubfach -com.fasterxml.jackson.core.json -com.fasterxml.jackson.core.json.async -com.fasterxml.jackson.core.sym -com.fasterxml.jackson.core.type -com.fasterxml.jackson.core.util +com.fasterxml.jackson.core +com.fasterxml.jackson.core.async +com.fasterxml.jackson.core.base +com.fasterxml.jackson.core.exc +com.fasterxml.jackson.core.filter +com.fasterxml.jackson.core.format +com.fasterxml.jackson.core.io +com.fasterxml.jackson.core.io.doubleparser +com.fasterxml.jackson.core.io.schubfach +com.fasterxml.jackson.core.json +com.fasterxml.jackson.core.json.async +com.fasterxml.jackson.core.sym +com.fasterxml.jackson.core.type +com.fasterxml.jackson.core.util diff --git a/src/support/javadoc/com.fasterxml.jackson.databind/package-list b/src/support/javadoc/com.fasterxml.jackson.databind/package-list index 3dce032c20..504478f4c2 100644 --- a/src/support/javadoc/com.fasterxml.jackson.databind/package-list +++ b/src/support/javadoc/com.fasterxml.jackson.databind/package-list @@ -1,23 +1,23 @@ -com.fasterxml.jackson.databind -com.fasterxml.jackson.databind.annotation -com.fasterxml.jackson.databind.cfg -com.fasterxml.jackson.databind.deser -com.fasterxml.jackson.databind.deser.impl -com.fasterxml.jackson.databind.deser.std -com.fasterxml.jackson.databind.exc -com.fasterxml.jackson.databind.ext -com.fasterxml.jackson.databind.introspect -com.fasterxml.jackson.databind.jdk14 -com.fasterxml.jackson.databind.json -com.fasterxml.jackson.databind.jsonFormatVisitors -com.fasterxml.jackson.databind.jsonschema -com.fasterxml.jackson.databind.jsontype -com.fasterxml.jackson.databind.jsontype.impl -com.fasterxml.jackson.databind.module -com.fasterxml.jackson.databind.node -com.fasterxml.jackson.databind.ser -com.fasterxml.jackson.databind.ser.impl -com.fasterxml.jackson.databind.ser.std -com.fasterxml.jackson.databind.type -com.fasterxml.jackson.databind.util -com.fasterxml.jackson.databind.util.internal +com.fasterxml.jackson.databind +com.fasterxml.jackson.databind.annotation +com.fasterxml.jackson.databind.cfg +com.fasterxml.jackson.databind.deser +com.fasterxml.jackson.databind.deser.impl +com.fasterxml.jackson.databind.deser.std +com.fasterxml.jackson.databind.exc +com.fasterxml.jackson.databind.ext +com.fasterxml.jackson.databind.introspect +com.fasterxml.jackson.databind.jdk14 +com.fasterxml.jackson.databind.json +com.fasterxml.jackson.databind.jsonFormatVisitors +com.fasterxml.jackson.databind.jsonschema +com.fasterxml.jackson.databind.jsontype +com.fasterxml.jackson.databind.jsontype.impl +com.fasterxml.jackson.databind.module +com.fasterxml.jackson.databind.node +com.fasterxml.jackson.databind.ser +com.fasterxml.jackson.databind.ser.impl +com.fasterxml.jackson.databind.ser.std +com.fasterxml.jackson.databind.type +com.fasterxml.jackson.databind.util +com.fasterxml.jackson.databind.util.internal diff --git a/src/support/javadoc/javax.validation/package-list b/src/support/javadoc/javax.validation/package-list index d37f56a720..35d7d788c6 100644 --- a/src/support/javadoc/javax.validation/package-list +++ b/src/support/javadoc/javax.validation/package-list @@ -1,9 +1,9 @@ -javax.validation -javax.validation.bootstrap -javax.validation.constraints -javax.validation.constraintvalidation -javax.validation.executable -javax.validation.groups -javax.validation.metadata -javax.validation.spi -javax.validation.valueextraction +javax.validation +javax.validation.bootstrap +javax.validation.constraints +javax.validation.constraintvalidation +javax.validation.executable +javax.validation.groups +javax.validation.metadata +javax.validation.spi +javax.validation.valueextraction diff --git a/src/support/javadoc/javax.ws.rs/package-list b/src/support/javadoc/javax.ws.rs/package-list index 810aa277d1..0f5b575cd3 100644 --- a/src/support/javadoc/javax.ws.rs/package-list +++ b/src/support/javadoc/javax.ws.rs/package-list @@ -1,6 +1,6 @@ -javax.ws.rs -javax.ws.rs.client -javax.ws.rs.container -javax.ws.rs.core -javax.ws.rs.ext -javax.ws.rs.sse +javax.ws.rs +javax.ws.rs.client +javax.ws.rs.container +javax.ws.rs.core +javax.ws.rs.ext +javax.ws.rs.sse diff --git a/src/support/javadoc/org.keycloak.client/package-list b/src/support/javadoc/org.keycloak.client/package-list index 417deb7052..1e9ccad13c 100644 --- a/src/support/javadoc/org.keycloak.client/package-list +++ b/src/support/javadoc/org.keycloak.client/package-list @@ -1 +1 @@ -org.keycloak.client.registration +org.keycloak.client.registration diff --git a/src/support/javadoc/org.keycloak.core/package-list b/src/support/javadoc/org.keycloak.core/package-list index 798d164b5f..52a90f9943 100644 --- a/src/support/javadoc/org.keycloak.core/package-list +++ b/src/support/javadoc/org.keycloak.core/package-list @@ -1,3 +1,3 @@ -org.keycloak -org.keycloak.representations -org.keycloak.representations.idm +org.keycloak +org.keycloak.representations +org.keycloak.representations.idm From d85c81755a3eb6db9c9f228a7d0e86e1a99f9dfd Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 17 Feb 2023 08:54:49 +0000 Subject: [PATCH 059/194] oops --- .../spinnaker/messages/bmp/BMPReadMemory.java | 79 ------------------- .../messages/bmp/BMPWriteMemory.java | 55 ------------- 2 files changed, 134 deletions(-) delete mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPReadMemory.java delete mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPWriteMemory.java 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/BMPReadMemory.java deleted file mode 100644 index 39319ec349..0000000000 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPReadMemory.java +++ /dev/null @@ -1,79 +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 - * - * http://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.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 java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.machine.board.BMPBoard; -import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; - -/** - * A request to read a region of memory from a BMP. The response payload is - * a read-only little-endian {@link ByteBuffer} intended to be read once. - *

- * Calls {@code cmd_read()} in {@code bmp_cmd.c}. - */ -public class BMPReadMemory extends BMPRequest { - private static int validate(int size) { - if (size < 1 || size > UDP_MESSAGE_MAX_SIZE) { - throw new IllegalArgumentException( - "size must be in range 1 to 256"); - } - return size; - } - - /** - * @param board - * which board to read the memory of - * @param address - * The positive base address to start the read from - * @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), - efficientTransferUnit(address, size).value); - } - - @Override - public Response getSCPResponse(ByteBuffer buffer) throws Exception { - return new Response(buffer); - } - - /** - * An SCP response to a request to read a region of memory on a chip. Note - * that it is up to the caller to manage the buffer position of the returned - * response if it is to be read from multiple times. - */ - protected final class Response - extends BMPRequest.PayloadedResponse { - Response(ByteBuffer buffer) throws UnexpectedResponseCodeException { - super("Read", CMD_READ, buffer); - } - - /** @return The data read, in a little-endian read-only buffer. */ - @Override - protected ByteBuffer parse(ByteBuffer buffer) { - return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN); - } - } -} 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/BMPWriteMemory.java deleted file mode 100644 index 7c746f842a..0000000000 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/BMPWriteMemory.java +++ /dev/null @@ -1,55 +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 - * - * http://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.bmp; - -import static uk.ac.manchester.spinnaker.messages.model.TransferUnit.efficientTransferUnit; -import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_WRITE; - -import java.nio.ByteBuffer; - -import uk.ac.manchester.spinnaker.machine.MemoryLocation; -import uk.ac.manchester.spinnaker.machine.board.BMPBoard; - -/** - * A request to write to memory on a BMP. There is no response payload. - *

- * Calls {@code cmd_write()} in {@code bmp_cmd.c}. - */ -public class BMPWriteMemory extends BMPRequest { - /** - * @param board - * the board with the BMP to write the memory of - * @param baseAddress - * The positive base address to start the write at - * @param data - * Between 1 and 256 bytes to write; the position of the - * buffer must be the point where the data starts, and the data - * 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, - ByteBuffer data) { - super(board, CMD_WRITE, baseAddress.address, data.remaining(), - efficientTransferUnit(baseAddress, data.remaining()).value, - data); - } - - @Override - public BMPRequest.BMPResponse getSCPResponse(ByteBuffer buffer) - throws Exception { - return new BMPRequest.BMPResponse("Write", CMD_WRITE, buffer); - } -} From 50eb1745181ad9b3d3c86a9eefa3385a514cf91a Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Fri, 17 Feb 2023 08:56:26 +0000 Subject: [PATCH 060/194] what happened there? --- .../uk/ac/manchester/spinnaker/front_end/TestFrontEnd.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/TestFrontEnd.java b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/TestFrontEnd.java index 2379c4310a..353fa492d8 100644 --- a/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/TestFrontEnd.java +++ b/SpiNNaker-front-end/src/test/java/uk/ac/manchester/spinnaker/front_end/TestFrontEnd.java @@ -159,7 +159,8 @@ public void loadAllCores() { }); tapSystemErrNormalized(() -> { - runMainExpecting(2, cmd, machineFile, dsFile, runFolder, "gorp"); + runMainExpecting(2, cmd, machineFile, dsFile, runFolder, + "gorp"); }); assertEquals("none", called.getValue()); @@ -203,8 +204,8 @@ protected void buildMaps(List gatherers) { "", "[]"); assertEquals("none", called.getValue()); - runMainExpecting(0, "dse_app_mon", gatherFile, machineFile, - dsFile, runFolder); + runMainExpecting(0, "dse_app_mon", gatherFile, machineFile, dsFile, + runFolder); assertEquals("mon", called.getValue()); } finally { CommandLineInterface.fastFactory = saved; From ef04f5dfabb04df0c1dcfb62e51df45174c7021b Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 1 Mar 2023 14:06:20 +0000 Subject: [PATCH 061/194] Missed a spot --- .../uk/ac/manchester/spinnaker/spalloc/SpallocJobAPI.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJobAPI.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJobAPI.java index 059eb26e17..729b849f90 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJobAPI.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/SpallocJobAPI.java @@ -201,8 +201,8 @@ default TransceiverInterface getTransceiver() } String bootHost = null; for (var c : connInfo) { - if (c.getChip().equals(ZERO_ZERO)) { - bootHost = c.getHostname(); + if (c.chip().equals(ZERO_ZERO)) { + bootHost = c.hostname(); } } if (bootHost == null) { @@ -212,8 +212,8 @@ default TransceiverInterface getTransceiver() uk.ac.manchester.spinnaker.connections.model.Connection>(); connections.add(new BootConnection(getByName(bootHost), null)); for (var c : connInfo) { - connections.add( - new SCPConnection(c.getChip(), getByName(c.getHostname()))); + connections + .add(new SCPConnection(c.chip(), getByName(c.hostname()))); } return new Transceiver(ver, connections); From 8bf29995fdfd0778728c0c0883d9b1b7e8c4a62c Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 1 Mar 2023 16:17:25 +0000 Subject: [PATCH 062/194] another oops --- .../java/uk/ac/manchester/spinnaker/alloc/db/SQLQueries.java | 2 -- 1 file changed, 2 deletions(-) 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 1ae9bd7bb6..804379b960 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 @@ -2787,8 +2787,6 @@ JOIN jobs USING (job_id) protected Resource findRectangleAt; /** -<<<<<<< HEAD -======= * Find an allocatable board with a specific board ID. (This will have been * previously converted from some other form of board coordinates.) * From 43534121cfc6a0e49ec4d7f38e39a3855fb2c84c Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 1 Mar 2023 16:38:52 +0000 Subject: [PATCH 063/194] Make some bits not public All they were doing is triggering javadoc grumbles --- .../spinnaker/alloc/ServiceConfig.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java index bb29d30c4b..ab8e22f3b2 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/ServiceConfig.java @@ -124,30 +124,34 @@ public class ServiceConfig extends Application { @Bean(name = "mainDatasource") @ConfigurationProperties(prefix = "spalloc.datasource") - public DataSource mainDatasource() { + @Role(ROLE_SUPPORT) + DataSource mainDatasource() { return DataSourceBuilder.create().build(); } @Bean(name = "historicalDatasource") @ConfigurationProperties(prefix = "spalloc.historical-data.datasource") - public DataSource historicalDatasource() { + @Role(ROLE_SUPPORT) + DataSource historicalDatasource() { return DataSourceBuilder.create().build(); } @Bean(name = "mainDatabase") - public JdbcTemplate mainDatabase( - @Qualifier("mainDatasource") DataSource ds) { + @Role(ROLE_SUPPORT) + JdbcTemplate mainDatabase(@Qualifier("mainDatasource") DataSource ds) { return new JdbcTemplate(ds); } @Bean(name = "historicalDatabase") - public JdbcTemplate historicalDatabase( + @Role(ROLE_SUPPORT) + JdbcTemplate historicalDatabase( @Qualifier("historicalDatasource") DataSource ds) { return new JdbcTemplate(ds); } @Bean(name = "mainTransactionManager") - public PlatformTransactionManager mainTransactionManager( + @Role(ROLE_INFRASTRUCTURE) + PlatformTransactionManager mainTransactionManager( @Qualifier("mainDatasource") DataSource ds) { return new JdbcTransactionManager(ds); } @@ -375,17 +379,6 @@ public String serviceUrl(String suffix) { } } - /*@Bean(name = "dataSource") - @ConfigurationProperties(prefix = "spring.datasource") - public DataSource dataSource() { - return DataSourceBuilder.create().build(); - } - - @Bean(name = "jdbcTemplate") - public JdbcTemplate applicationDataConnection(){ - return new JdbcTemplate(dataSource()); - } */ - @Autowired private ApplicationContext ctx; From 9d929c6b902e0431c0b6c273a05783c8a65c6926 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 1 Mar 2023 17:02:37 +0000 Subject: [PATCH 064/194] Tinkering --- .../storage/sqlite/SQLiteProxyStorage.java | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java index 7c0ea4c51e..87d1abe97a 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java @@ -34,7 +34,10 @@ abstract class SQLiteProxyStorage extends SQLiteConnectionManager implements ProxyAwareStorage { - + /** + * @param connProvider + * The source of database connections. + */ protected SQLiteProxyStorage(ConnectionProvider connProvider) { super(connProvider); } @@ -52,7 +55,7 @@ public ProxyInformation getProxyInformation() throws StorageException { * @return The proxy information. * @throws SQLException * If there is an error reading the database. - * @throws IllegalStateException + * @throws Unreachable * If a bad row is retrieved; should be unreachable if SQL is * synched to code. */ @@ -68,31 +71,21 @@ private ProxyInformation getProxyInfo(Connection conn) throws SQLException { var kind = rs.getString("kind"); var name = rs.getString("name"); var value = rs.getString("value"); - if (name == null || value == null) { + if (kind == null || name == null || value == null) { continue; } switch (kind) { - case SPALLOC: + case SPALLOC -> { switch (name) { - case SPALLOC_URI -> { - spallocUri = value; - } - case PROXY_URI -> { - jobUri = value; - } - default -> - throw new IllegalStateException("unreachable reached"); + case SPALLOC_URI -> spallocUri = value; + case PROXY_URI -> jobUri = value; + default -> throw new Unreachable(); } - break; + } - case COOKIE: - cookies.put(name, value); - break; - case HEADER: - headers.put(name, value); - break; - default: - throw new IllegalStateException("unreachable reached"); + case COOKIE -> cookies.put(name, value); + case HEADER -> headers.put(name, value); + default -> throw new Unreachable(); } } } @@ -102,4 +95,13 @@ private ProxyInformation getProxyInfo(Connection conn) throws SQLException { } return new ProxyInformation(spallocUri, jobUri, headers, cookies); } + + /** Thrown when an unreachable state is reached. */ + private static class Unreachable extends IllegalStateException { + private static final long serialVersionUID = 1L; + + Unreachable() { + super("unreachable reached"); + } + } } From bc1a71ae1d8ef114aaa338fba26cb108a4ac35e4 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 2 Mar 2023 10:08:31 +0000 Subject: [PATCH 065/194] Stupidity in checkstyle rules --- .../manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java index 87d1abe97a..ef0f782ef4 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java @@ -59,6 +59,7 @@ public ProxyInformation getProxyInformation() throws StorageException { * If a bad row is retrieved; should be unreachable if SQL is * synched to code. */ + @SuppressWarnings("checkstyle:InnerAssignment") // Rule is misapplying private ProxyInformation getProxyInfo(Connection conn) throws SQLException { String spallocUri = null; String jobUri = null; From 39e630ddd8ce1b79ba182a74e357fc333667677f Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 9 Mar 2023 16:34:29 +0000 Subject: [PATCH 066/194] A bunch of cleaning up Especially making things be records which should be, but also stripping a few redundant classes and fixing up a few instanceofs. --- .../alloc/admin/MachineStateControl.java | 21 +- .../spinnaker/alloc/admin/UserControl.java | 35 ++- .../alloc/allocator/AllocatorTask.java | 232 +++++++++--------- .../spinnaker/alloc/allocator/Spalloc.java | 77 ++---- .../spinnaker/alloc/bmp/BlacklistStore.java | 33 ++- .../ac/manchester/spinnaker/alloc/db/Row.java | 8 +- .../alloc/proxy/ProxyUDPConnection.java | 6 +- .../alloc/client/SpallocClientFactory.java | 3 +- .../connections/IPAddressConnection.java | 2 +- .../spinnaker/connections/UDPPacket.java | 37 +-- .../model/InvalidPacketException.java | 49 ---- .../connections/model/MessageHandler.java | 1 + .../spinnaker/messages/boot/BootMessage.java | 3 +- .../boot/SystemVariableBootValues.java | 2 +- .../transceiver/ApplicationRunProcess.java | 2 +- .../spinnaker/transceiver/FillProcess.java | 2 +- .../transceiver/FixedRouteControlProcess.java | 2 +- .../transceiver/GetCPUInfoProcess.java | 2 +- .../transceiver/GetMachineProcess.java | 2 +- .../spinnaker/transceiver/GetTagsProcess.java | 2 +- .../transceiver/ReadMemoryProcess.java | 2 +- .../transceiver/RouterControlProcess.java | 2 +- .../transceiver/RuntimeControlProcess.java | 2 +- .../spinnaker/transceiver/UDPTransceiver.java | 20 +- .../transceiver/WriteMemoryFloodProcess.java | 2 +- .../front_end/CommandLineInterface.java | 10 +- .../download/GatherProtocolMessage.java | 4 +- .../dse/FastExecuteDataSpecification.java | 8 +- .../dse/HostExecuteDataSpecification.java | 2 +- .../front_end/dse/ThrottledConnection.java | 2 +- .../spinnaker/front_end/iobuf/Replacer.java | 2 +- .../storage/BufferManagerStorage.java | 2 +- .../spinnaker/storage/ConnectionProvider.java | 46 ---- .../spinnaker/storage/DSEStorage.java | 2 +- .../spinnaker/storage/DatabaseAPI.java | 16 +- .../spinnaker/storage/DatabaseEngine.java | 18 +- .../spinnaker/storage/ProxyAwareStorage.java | 35 --- .../storage/sqlite/SQLiteBufferStorage.java | 15 +- .../storage/sqlite/SQLiteDataSpecStorage.java | 12 +- .../storage/sqlite/SQLiteProxyStorage.java | 108 -------- ...nectionManager.java => SQLiteStorage.java} | 97 +++++++- 41 files changed, 373 insertions(+), 555 deletions(-) delete mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/model/InvalidPacketException.java delete mode 100644 SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ConnectionProvider.java delete mode 100644 SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyAwareStorage.java delete mode 100644 SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java rename SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/{SQLiteConnectionManager.java => SQLiteStorage.java} (59%) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index beb6cdc000..28ea219278 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -366,28 +366,23 @@ public List getMachineTagging() { }); } - private class MachineNameId { - int id; - - String name; - - MachineNameId(Row row) { - id = row.getInt("machine_id"); - name = row.getString("machine_name"); - } - } - /** * @return The unacknowledged reports about boards with potential problems * in existing machines, categorised by machine. */ public Map> getMachineReports() { + record MachineNameId(int id, String name) { + MachineNameId(Row row) { + this(row.getInt("machine_id"), row.getString("machine_name")); + } + } + return executeRead(conn -> { try (var getMachines = conn.query(GET_ALL_MACHINES); var getMachineReports = conn.query(GET_MACHINE_REPORTS)) { return Row.stream(getMachines.call(MachineNameId::new, true)) - .toMap(m -> m.name, m -> getMachineReports.call( - BoardIssueReport::new, m.id)); + .toMap(MachineNameId::name, m -> getMachineReports + .call(BoardIssueReport::new, m.id())); } }); } diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java index 4626b7e95e..3b39f41fc6 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/UserControl.java @@ -597,24 +597,6 @@ public PasswordChangeRecord updateUser(Principal principal, } } - /** - * 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) - */ - private record GetUserResult(PasswordChangeRecord baseUser, - String oldEncPass) { - private GetUserResult(Row row) { - this(passChange(row), row.getString("encrypted_password")); - } - } - /** * Back end of {@link #updateUser(Principal,PasswordChangeRecord)}. *

@@ -632,6 +614,23 @@ private GetUserResult(Row row) { */ 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())) 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 b8b37f92a1..5fe144624f 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 @@ -161,17 +161,6 @@ public 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 sealed class PowerSQL extends AbstractSQL permits AllocSQL, DestroySQL { @@ -342,6 +331,7 @@ public void close() { } } + /** Encapsulates the task to do a particular allocation. */ private class AllocTask { final int id; @@ -563,100 +553,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 + }; + } } } @@ -683,17 +686,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.allocStream().forEach((a) -> writeAllocs.call(a.args())); - copied.jobStream().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.allocStream() - .forEach((a) -> deleteAllocs.call(a.allocId)); - copied.jobStream().forEach((j) -> deleteJobs.call(j.jobId)); + .forEach(a -> deleteAllocs.call(a.allocId())); + copied.jobStream().forEach(j -> deleteJobs.call(j.jobId())); }); return copied; } @@ -1043,6 +1046,13 @@ private boolean setPower(PowerSQL sql, int jobId, PowerState power, // 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)); + } + } + if (power == ON) { /* * This is a bit of a trickier case, as we need to say which links @@ -1050,10 +1060,10 @@ private boolean setPower(PowerSQL sql, int jobId, PowerState power, * 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 boardId : boards) { var toChange = perimeterLinks.getOrDefault(boardId, 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 1d6918d5c4..fa1e736f32 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 @@ -515,17 +515,6 @@ public Integer board(CreateBoard b) { }); } - private class UserQuota { - Long quota; - - int groupId; - - UserQuota(Row row) { - quota = row.getLong("quota"); - groupId = row.getInt("group_id"); - } - } - /** * Work out what the ID of the group that a job will be accounted against * is. @@ -542,6 +531,16 @@ private class UserQuota { * If we can't get a definite group to account against. */ private int selectGroup(Connection conn, String user, String groupName) { + record UserQuota(Long quota, int groupId) { + UserQuota(Row row) { + this(row.getLong("quota"), row.getInt("group_id")); + } + + boolean meaningful() { + return isNull(quota) || quota > 0L; + } + } + if (nonNull(groupName)) { try (var getGroup = conn.query(GET_GROUP_BY_NAME_AND_MEMBER)) { return getGroup.call1(integer("group_id"), user, groupName) @@ -554,9 +553,8 @@ private int selectGroup(Connection conn, String user, String groupName) { try (var listGroups = conn.query(GET_GROUPS_AND_QUOTAS_OF_USER)) { // No name given; need to guess. return Row.stream(listGroups.call(UserQuota::new, user)) - .filter(q -> isNull(q.quota) - || q.quota > 0L) - .map(q -> q.groupId).first() + .filter(UserQuota::meaningful) + .map(UserQuota::groupId).first() .orElseThrow(() -> new NoSuchGroupException( "user %s is not a member of any " + "groups with quota left", @@ -570,17 +568,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. * @@ -599,6 +586,12 @@ 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)) { @@ -677,14 +670,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")); } } @@ -727,28 +715,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")); } - } /** 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/db/Row.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/db/Row.java index 28fd9b4e5a..d3fccc20c3 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; }); 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 8ae58eeb67..223e9abfae 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 @@ -260,11 +260,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-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 394b4b41f5..d44885d756 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 @@ -297,7 +297,8 @@ private Job getJob(ProxyInformation proxyInfo) throws IOException { 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; 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/UDPPacket.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/UDPPacket.java index 7925208c50..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,36 +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/messages/boot/BootMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessage.java index 53880b75cb..dae13f5599 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessage.java @@ -25,7 +25,8 @@ * A message used for booting the board. Note that boot messages are big endian, * unlike the rest of SpiNNaker. */ -public class BootMessage implements SerializableMessage { +public sealed class BootMessage implements SerializableMessage + permits BootDataBlock, EndOfBootMessages, StartOfBootMessages { private static final short BOOT_MESSAGE_VERSION = 1; private static final int BOOT_PACKET_SIZE = 256 * WORD_SIZE; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java index e658ba8e3e..098b57f5c9 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/SystemVariableBootValues.java @@ -31,7 +31,7 @@ * Default values of the system variables that get passed to SpiNNaker during * boot. */ -public class SystemVariableBootValues implements SerializableMessage { +public final class SystemVariableBootValues implements SerializableMessage { /** The size of the boot variable block, in bytes. */ static final int BOOT_VARIABLE_SIZE = 256; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ApplicationRunProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ApplicationRunProcess.java index 49ffeb1364..0fd993d01a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ApplicationRunProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ApplicationRunProcess.java @@ -24,7 +24,7 @@ import uk.ac.manchester.spinnaker.messages.scp.ApplicationRun; /** Launch an application. */ -class ApplicationRunProcess extends TxrxProcess { +final class ApplicationRunProcess extends TxrxProcess { /** * Create. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java index 50533e79e7..7f7e59014f 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java @@ -34,7 +34,7 @@ import uk.ac.manchester.spinnaker.messages.scp.WriteMemory; /** A process for filling memory. */ -class FillProcess extends TxrxProcess { +final class FillProcess extends TxrxProcess { private static final Logger log = getLogger(FillProcess.class); private static final int ALIGNMENT = 4; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FixedRouteControlProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FixedRouteControlProcess.java index 499125a744..e22f64982c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FixedRouteControlProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FixedRouteControlProcess.java @@ -28,7 +28,7 @@ import uk.ac.manchester.spinnaker.messages.scp.FixedRouteRead; /** Load a fixed route routing entry onto a chip, and read it back again. */ -class FixedRouteControlProcess extends TxrxProcess { +final class FixedRouteControlProcess extends TxrxProcess { /** * @param connectionSelector * How to select how to communicate. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetCPUInfoProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetCPUInfoProcess.java index d1a4033534..1e5ef61992 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetCPUInfoProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetCPUInfoProcess.java @@ -32,7 +32,7 @@ /** * Get the CPU information structure for a set of processors. */ -class GetCPUInfoProcess extends TxrxProcess { +final class GetCPUInfoProcess extends TxrxProcess { /** * @param connectionSelector * How to select how to communicate. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java index b04957d583..3e1a64257b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetMachineProcess.java @@ -53,7 +53,7 @@ import uk.ac.manchester.spinnaker.messages.scp.ReadMemory; /** A process for getting the machine details over a set of connections. */ -class GetMachineProcess extends TxrxProcess { +final class GetMachineProcess extends TxrxProcess { private static final Logger log = getLogger(GetMachineProcess.class); /** A dictionary of (x, y) → ChipInfo. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetTagsProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetTagsProcess.java index ca2057f1b3..2361671af5 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetTagsProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/GetTagsProcess.java @@ -29,7 +29,7 @@ import uk.ac.manchester.spinnaker.messages.scp.IPTagGetInfo; /** Gets IP tags and reverse IP tags. */ -class GetTagsProcess extends TxrxProcess { +final class GetTagsProcess extends TxrxProcess { /** * @param connectionSelector * How to select how to communicate. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ReadMemoryProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ReadMemoryProcess.java index 53373fdf44..06dcc9dfdc 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ReadMemoryProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ReadMemoryProcess.java @@ -36,7 +36,7 @@ import uk.ac.manchester.spinnaker.transceiver.Accumulator.FileAccumulator; /** A process for reading memory on a SpiNNaker chip. */ -class ReadMemoryProcess extends TxrxProcess { +final class ReadMemoryProcess extends TxrxProcess { /** * @param connectionSelector * How to select how to communicate. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RouterControlProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RouterControlProcess.java index dc711b1135..62b80e6774 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RouterControlProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RouterControlProcess.java @@ -47,7 +47,7 @@ * Access to the control facilities for a set of routers. Depends on access to * the extra monitor cores running on those chips. */ -class RouterControlProcess extends TxrxProcess { +final class RouterControlProcess extends TxrxProcess { private static final int REGISTER = 4; private static final int NUM_REGISTERS = 16; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java index e148b6e0f3..617b16b669 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java @@ -51,7 +51,7 @@ * * @author Donal Fellows */ -class RuntimeControlProcess extends TxrxProcess { +final class RuntimeControlProcess extends TxrxProcess { private static final int BUF_HEADER_BYTES = 16; private static final int BLOCK_HEADER_BYTES = 16; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UDPTransceiver.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UDPTransceiver.java index 162e276efa..3cc45ef24d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UDPTransceiver.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/UDPTransceiver.java @@ -196,10 +196,14 @@ private interface ThrowingSupplier { /** * Wrap any IOException thrown into an UncheckedIOException. - * @param Type of result - * @param s Produces result or throws. + * + * @param + * Type of result + * @param s + * Produces result or throws. * @return Result of s - * @throws UncheckedIOException If supplier throws IOException + * @throws UncheckedIOException + * If supplier throws IOException */ private static T wrap(ThrowingSupplier s) { try { @@ -211,10 +215,14 @@ private static T wrap(ThrowingSupplier s) { /** * Unwrap any UncheckedIOException thrown as its IOException. - * @param Type of result - * @param s Produces result or throws. + * + * @param + * Type of result + * @param s + * Produces result or throws. * @return Result of s - * @throws IOException If supplier throws UncheckedIOException + * @throws IOException + * If supplier throws UncheckedIOException */ private static T unwrap(Supplier s) throws IOException { try { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java index f53406d4ca..d8b0b4e2e8 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/WriteMemoryFloodProcess.java @@ -36,7 +36,7 @@ import uk.ac.manchester.spinnaker.messages.scp.FloodFillStart; /** A process for writing memory on multiple SpiNNaker chips at once. */ -class WriteMemoryFloodProcess extends TxrxProcess { +final class WriteMemoryFloodProcess extends TxrxProcess { /** * @param connectionSelector * How to select how to communicate. diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java index f2e74cc328..c192f099e5 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java @@ -81,7 +81,7 @@ import uk.ac.manchester.spinnaker.storage.BufferManagerStorage; import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; import uk.ac.manchester.spinnaker.storage.DatabaseEngine; -import uk.ac.manchester.spinnaker.storage.ProxyAwareStorage; +import uk.ac.manchester.spinnaker.storage.DatabaseAPI; import uk.ac.manchester.spinnaker.storage.StorageException; import uk.ac.manchester.spinnaker.transceiver.SpinnmanException; import uk.ac.manchester.spinnaker.transceiver.Transceiver; @@ -685,12 +685,12 @@ private static BufferManagerStorage getBufferManagerDB(File dbFile) { } private static SpallocClient.Job getJob( - DatabaseEngine databaseEngine) + DatabaseEngine databaseEngine) throws StorageException, IOException { return getJob(databaseEngine.getStorageInterface()); } - private static SpallocClient.Job getJob(ProxyAwareStorage storage) + private static SpallocClient.Job getJob(DatabaseAPI storage) throws StorageException, IOException { return getJobFromProxyInfo(storage.getProxyInformation()); } @@ -709,8 +709,8 @@ private static TransceiverInterface getTransceiver(Machine machine, txrx = job.getTransceiver(); } var scpSelector = txrx.getScampConnectionSelector(); - if (scpSelector instanceof MachineAware) { - ((MachineAware) scpSelector).setMachine(machine); + if (scpSelector instanceof MachineAware ma) { + ma.setMachine(machine); } return txrx; } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/GatherProtocolMessage.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/GatherProtocolMessage.java index cc9afc7c3d..da89fa2270 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/GatherProtocolMessage.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/GatherProtocolMessage.java @@ -30,7 +30,9 @@ * * @author Donal Fellows */ -public abstract class GatherProtocolMessage extends SDPMessage { +public abstract sealed class GatherProtocolMessage extends SDPMessage + permits ClearMessage, StartSendingMessage, + MissingSequenceNumbersMessage { /** * Create a protocol message. * diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index f98a1f65e9..269849fb88 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -346,7 +346,7 @@ baseAddress, toUnsignedLong(size), timeTaken, mbs, * @author Donal Fellows * @author Alan Stokes */ - private class BoardWorker implements AutoCloseable { + private final class BoardWorker implements AutoCloseable { private Ethernet board; private DSEStorage storage; @@ -498,7 +498,7 @@ private int loadCoreFromExecutor(CoreToLoad ctl, Gather gather, * @author Donal Fellows */ @SuppressWarnings("serial") - private class MissingRecorder extends ArrayDeque + private final class MissingRecorder extends ArrayDeque implements AutoCloseable { MissingRecorder() { missingSequenceNumbers = this; @@ -833,7 +833,7 @@ private void retransmitMissingPackets(GathererProtocol protocol, * * @author Donal Fellows */ - private class GathererProtocol extends FastDataInProtocol { + private final class GathererProtocol extends FastDataInProtocol { private GathererProtocol(ChipLocation chip, boolean ignored) { super(machine, gathererForChip.get(chip), monitorForChip.get(chip)); } @@ -856,7 +856,7 @@ private GathererProtocol(ChipLocation chip, boolean ignored) { * * @author Alan Stokes */ - private static class SeenFlags { + private static final class SeenFlags { boolean seenEnd; boolean seenAll; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java index 0e48576692..f08a5a3d9e 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java @@ -210,7 +210,7 @@ private void loadBoard(Ethernet board, DSEStorage storage, Progress bar, } } - private class BoardWorker { + private final class BoardWorker { private final Ethernet board; private final DSEStorage storage; diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ThrottledConnection.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ThrottledConnection.java index 0589976724..f315d552f4 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ThrottledConnection.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/ThrottledConnection.java @@ -50,7 +50,7 @@ * * @author Donal Fellows */ -class ThrottledConnection implements Closeable { +final class ThrottledConnection implements Closeable { private static final Logger log = getLogger(ThrottledConnection.class); /** The minimum interval between messages, in nanoseconds. */ diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java index d842f21e40..7f6feb8ee0 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/iobuf/Replacer.java @@ -39,7 +39,7 @@ * * @author Donal Fellows */ -class Replacer { +final class Replacer { private static final Logger log = getLogger(Replacer.class); private static final Pattern FORMAT_SEQUENCE = diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java index 213f5a0943..6044005600 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/BufferManagerStorage.java @@ -32,7 +32,7 @@ * * @author Donal Fellows */ -public interface BufferManagerStorage extends ProxyAwareStorage { +public interface BufferManagerStorage extends DatabaseAPI { /** * Retrieves some bytes from the database. The bytes represent the contents * of a DSE region of a particular SpiNNaker core. diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ConnectionProvider.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ConnectionProvider.java deleted file mode 100644 index 7c190df012..0000000000 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ConnectionProvider.java +++ /dev/null @@ -1,46 +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.storage; - -import java.sql.Connection; -import java.sql.SQLException; - -/** - * Indicates a class that can provide database connections to - * suitably-configured databases. - * - * @author Donal Fellows - * @param - * The type of the higher-level access interface that can be used to - * work with the database this class makes connections to. - */ -public interface ConnectionProvider { - /** - * Get a connection to a database, creating it if needed. - * - * @return The configured connection to the database. The database will have - * been seeded with DDL if necessary. - * @throws SQLException - * If anything goes wrong. - */ - Connection getConnection() throws SQLException; - - /** - * @return a storage interface that is suitable for providing support for a - * particular API. - */ - APIType getStorageInterface(); -} diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java index 517b7d1dc7..a68f932b51 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java @@ -31,7 +31,7 @@ * * @author Donal Fellows */ -public interface DSEStorage extends ProxyAwareStorage { +public interface DSEStorage extends DatabaseAPI { /** * See how many DSE loading actions have to be done. * diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java index d75804d00a..1a83973234 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseAPI.java @@ -16,9 +16,21 @@ package uk.ac.manchester.spinnaker.storage; /** - * Interface that real database interfaces are subclasses of. + * Interface that real database interfaces are subclasses of. All database + * interfaces defined by this know how to read the proxy information from the + * DB. * * @author Donal Fellows */ -public sealed interface DatabaseAPI permits ProxyAwareStorage { +public interface DatabaseAPI { + /** + * Get the proxy information from the database. + * + * @return The proxy information, or {@code null} if none defined. When + * there is no proxy, only direct connections to SpiNNaker are + * possible. + * @throws StorageException + * If anything goes wrong. + */ + ProxyInformation getProxyInformation() throws StorageException; } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java index b5240e2a92..d560893c5a 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DatabaseEngine.java @@ -30,7 +30,7 @@ import com.google.errorprone.annotations.MustBeClosed; /** - * The database engine interface. Based on SQLite. + * The database engine interface. Assumed to be based on SQLite. * * @author Donal Fellows * @param @@ -38,7 +38,6 @@ * work with the database this class makes connections to. */ public abstract sealed class DatabaseEngine - implements ConnectionProvider permits BufferManagerDatabaseEngine, DSEDatabaseEngine { private static final Logger log = getLogger(DatabaseEngine.class); @@ -66,7 +65,14 @@ public DatabaseEngine(File dbFile) { log.info("will manage database at {}", dbFile.getAbsolutePath()); } - @Override + /** + * Get a connection to a database, creating it if needed. + * + * @return The configured connection to the database. The database will have + * been seeded with DDL if necessary. + * @throws SQLException + * If anything goes wrong. + */ @MustBeClosed public Connection getConnection() throws SQLException { if (log.isDebugEnabled()) { @@ -85,6 +91,12 @@ public Connection getConnection() throws SQLException { return conn; } + /** + * @return a storage interface that is suitable for providing support for a + * particular API. + */ + public abstract APIType getStorageInterface(); + /** * @return The DDL for initialising this kind of database. */ diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyAwareStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyAwareStorage.java deleted file mode 100644 index b2452944ff..0000000000 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/ProxyAwareStorage.java +++ /dev/null @@ -1,35 +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.storage; - -/** - * Storage interface that knows how to get information about the proxy system - * from the DB. - * - * @author Donal Fellows - */ -public non-sealed interface ProxyAwareStorage extends DatabaseAPI { - /** - * Get the proxy information from the database. - * - * @return The proxy information, or {@code null} if none defined. When - * there is no proxy, only direct connections to SpiNNaker are - * possible. - * @throws StorageException - * If anything goes wrong. - */ - ProxyInformation getProxyInformation() throws StorageException; -} diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java index 2747a778d6..65d5c93fd6 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteBufferStorage.java @@ -58,20 +58,19 @@ * * @author Donal Fellows */ -public final class SQLiteBufferStorage - extends SQLiteProxyStorage - implements BufferManagerStorage { +public final class SQLiteBufferStorage extends + SQLiteStorage implements BufferManagerStorage { private static final Logger log = getLogger(SQLiteBufferStorage.class); /** * Create an instance. * - * @param connectionProvider - * The connection provider that will be asked for how to talk SQL - * to the database. + * @param db + * The database engine that will be asked for how to talk SQL to + * the database. */ - public SQLiteBufferStorage(BufferManagerDatabaseEngine connectionProvider) { - super(connectionProvider); + public SQLiteBufferStorage(BufferManagerDatabaseEngine db) { + super(db); } private static int getRecordingCore(Connection conn, CoreLocation core) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index fad1949b0f..5372bfe644 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -45,17 +45,17 @@ * * @author Donal Fellows */ -public final class SQLiteDataSpecStorage extends SQLiteProxyStorage +public final class SQLiteDataSpecStorage extends SQLiteStorage implements DSEStorage { /** * Create an instance. * - * @param connectionProvider - * The connection provider that will be asked for how to talk SQL - * to the database. + * @param db + * The database engine that will be asked for how to talk SQL to + * the database. */ - public SQLiteDataSpecStorage(DSEDatabaseEngine connectionProvider) { - super(connectionProvider); + public SQLiteDataSpecStorage(DSEDatabaseEngine db) { + super(db); } @Override diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java deleted file mode 100644 index 72c054e6b3..0000000000 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteProxyStorage.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2022 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.storage.sqlite; - -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_PROXY_INFORMATION; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.COOKIE; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.HEADER; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SPALLOC; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.PROXY_URI; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SPALLOC_URI; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.HashMap; - -import uk.ac.manchester.spinnaker.storage.ConnectionProvider; -import uk.ac.manchester.spinnaker.storage.DatabaseAPI; -import uk.ac.manchester.spinnaker.storage.ProxyAwareStorage; -import uk.ac.manchester.spinnaker.storage.ProxyInformation; -import uk.ac.manchester.spinnaker.storage.StorageException; - -abstract class SQLiteProxyStorage - extends SQLiteConnectionManager implements ProxyAwareStorage { - /** - * @param connProvider - * The source of database connections. - */ - protected SQLiteProxyStorage(ConnectionProvider connProvider) { - super(connProvider); - } - - @Override - public ProxyInformation getProxyInformation() throws StorageException { - return callR(conn -> getProxyInfo(conn), "get proxy"); - } - - /** - * Get the proxy information from a database. - * - * @param conn - * The connection to read the data from. - * @return The proxy information. - * @throws SQLException - * If there is an error reading the database. - * @throws Unreachable - * If a bad row is retrieved; should be unreachable if SQL is - * synched to code. - */ - @SuppressWarnings("checkstyle:InnerAssignment") // Rule is misapplying - private ProxyInformation getProxyInfo(Connection conn) throws SQLException { - String spallocUri = null; - String jobUri = null; - var headers = new HashMap(); - var cookies = new HashMap(); - - try (var s = conn.prepareStatement(GET_PROXY_INFORMATION); - var rs = s.executeQuery()) { - while (rs.next()) { - var kind = rs.getString("kind"); - var name = rs.getString("name"); - var value = rs.getString("value"); - if (kind == null || name == null || value == null) { - continue; - } - switch (kind) { - case SPALLOC -> { - switch (name) { - case SPALLOC_URI -> spallocUri = value; - case PROXY_URI -> jobUri = value; - default -> throw new Unreachable(); - } - } - - case COOKIE -> cookies.put(name, value); - case HEADER -> headers.put(name, value); - default -> throw new Unreachable(); - } - } - } - // If we don't have all pieces of info, we can't talk to the proxy - if (spallocUri == null || jobUri == null) { - return null; - } - return new ProxyInformation(spallocUri, jobUri, headers, cookies); - } - - /** Thrown when an unreachable state is reached. */ - private static class Unreachable extends IllegalStateException { - private static final long serialVersionUID = 1L; - - Unreachable() { - super("unreachable reached"); - } - } -} diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteStorage.java similarity index 59% rename from SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java rename to SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteStorage.java index 0c23d4d30e..3f3ee8331a 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteConnectionManager.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteStorage.java @@ -17,17 +17,25 @@ import static org.slf4j.LoggerFactory.getLogger; import static org.sqlite.SQLiteErrorCode.SQLITE_BUSY; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.COOKIE; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_PROXY_INFORMATION; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.HEADER; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.PROXY_URI; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SPALLOC; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SPALLOC_URI; import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; import org.slf4j.Logger; import org.sqlite.SQLiteException; import com.google.errorprone.annotations.concurrent.GuardedBy; -import uk.ac.manchester.spinnaker.storage.ConnectionProvider; import uk.ac.manchester.spinnaker.storage.DatabaseAPI; +import uk.ac.manchester.spinnaker.storage.DatabaseEngine; +import uk.ac.manchester.spinnaker.storage.ProxyInformation; import uk.ac.manchester.spinnaker.storage.StorageException; /** @@ -38,20 +46,21 @@ * The type of the connections used inside this class. Probably the * type of the concrete subclass of this class. */ -abstract class SQLiteConnectionManager { - private static final Logger log = getLogger(SQLiteConnectionManager.class); +abstract sealed class SQLiteStorage + implements DatabaseAPI + permits SQLiteBufferStorage, SQLiteDataSpecStorage { + private static final Logger log = getLogger(SQLiteStorage.class); @GuardedBy("itself") - private final ConnectionProvider connProvider; + private final DatabaseEngine db; /** - * @param connProvider + * @param db * The source of database connections. * @see Connection */ - protected SQLiteConnectionManager( - ConnectionProvider connProvider) { - this.connProvider = connProvider; + protected SQLiteStorage(DatabaseEngine db) { + this.db = db; } /** @@ -108,8 +117,8 @@ interface CallWithoutResult { */ final T callR(CallWithResult call, String actionDescription) throws StorageException { - synchronized (connProvider) { - try (var conn = connProvider.getConnection()) { + synchronized (db) { + try (var conn = db.getConnection()) { startTransaction(conn); try { var result = call.call(conn); @@ -137,8 +146,8 @@ final T callR(CallWithResult call, String actionDescription) */ final void callV(CallWithoutResult call, String actionDescription) throws StorageException { - synchronized (connProvider) { - try (var conn = connProvider.getConnection()) { + synchronized (db) { + try (var conn = db.getConnection()) { startTransaction(conn); try { call.call(conn); @@ -175,4 +184,68 @@ private void startTransaction(Connection conn) throws SQLException { } throw new SQLiteException("database very busy", code); } + + @Override + public ProxyInformation getProxyInformation() throws StorageException { + return callR(conn -> getProxyInfo(conn), "get proxy"); + } + + /** + * Get the proxy information from a database. + * + * @param conn + * The connection to read the data from. + * @return The proxy information. + * @throws SQLException + * If there is an error reading the database. + * @throws Unreachable + * If a bad row is retrieved; should be unreachable if SQL is + * synched to code. + */ + @SuppressWarnings("checkstyle:InnerAssignment") // Rule is misapplying + private ProxyInformation getProxyInfo(Connection conn) throws SQLException { + String spallocUri = null; + String jobUri = null; + var headers = new HashMap(); + var cookies = new HashMap(); + + try (var s = conn.prepareStatement(GET_PROXY_INFORMATION); + var rs = s.executeQuery()) { + while (rs.next()) { + var kind = rs.getString("kind"); + var name = rs.getString("name"); + var value = rs.getString("value"); + if (kind == null || name == null || value == null) { + continue; + } + switch (kind) { + case SPALLOC -> { + switch (name) { + case SPALLOC_URI -> spallocUri = value; + case PROXY_URI -> jobUri = value; + default -> throw new Unreachable(); + } + } + + case COOKIE -> cookies.put(name, value); + case HEADER -> headers.put(name, value); + default -> throw new Unreachable(); + } + } + } + // If we don't have all pieces of info, we can't talk to the proxy + if (spallocUri == null || jobUri == null) { + return null; + } + return new ProxyInformation(spallocUri, jobUri, headers, cookies); + } + + /** Thrown when an unreachable state is reached. */ + private static class Unreachable extends IllegalStateException { + private static final long serialVersionUID = 1L; + + Unreachable() { + super("unreachable reached"); + } + } } From cfeea3b60d61d20a6f5782bdf714be3f1d7c79fc Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 9 Mar 2023 16:37:47 +0000 Subject: [PATCH 067/194] RunAsUserToken is strongly deprecated and not actually used --- .../spinnaker/alloc/security/LocalAuthProviderImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 e24b7fada3..3dc2763cd7 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 @@ -49,7 +49,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; @@ -300,7 +299,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 From cca8939ba80223e2e3eb451922e52b7ed2b920ba Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 5 Apr 2023 15:47:59 +0100 Subject: [PATCH 068/194] Bump some versions --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 276456e9af..c3bac4bb11 100644 --- a/pom.xml +++ b/pom.xml @@ -42,8 +42,8 @@ limitations under the License. 2.0.7 2.20.0 - 6.0.3 - 3.0.1 + 6.0.7 + 3.0.5 - 6.0.1 + 6.0.2 4.0.0 2.14.2 2.14 3.41.2.1 21.0.2 - 4.18.1 + 4.18.2 1.0.5 2.7.3 2.18.0 From 07bd90cbe4334a2067b7763222883ba92284bb35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 11:08:26 +0000 Subject: [PATCH 069/194] Bump jackson.version from 2.14.2 to 2.15.0 Bumps `jackson.version` from 2.14.2 to 2.15.0. Updates `jackson-bom` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.14.2...jackson-bom-2.15.0) Updates `jackson-module-jaxb-annotations` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson-modules-base/compare/jackson-modules-base-2.14.2...jackson-modules-base-2.15.0) Updates `jackson-module-parameter-names` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson-modules-java8/compare/jackson-modules-java8-2.14.2...jackson-modules-java8-2.15.0) Updates `jackson-annotations` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `jackson-core` from 2.14.2 to 2.15.0 - [Release notes](https://github.com/FasterXML/jackson-core/releases) - [Changelog](https://github.com/FasterXML/jackson-core/blob/jackson-core-2.15.0/release.properties) - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.14.2...jackson-core-2.15.0) Updates `jackson-databind` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `jackson-jaxrs-json-provider` from 2.14.2 to 2.15.0 Updates `jackson-jaxrs-base` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson-jaxrs-providers/compare/jackson-jaxrs-providers-2.14.2...jackson-jaxrs-providers-2.15.0) Updates `jackson-datatype-jdk8` from 2.14.2 to 2.15.0 Updates `jackson-datatype-jsr310` from 2.14.2 to 2.15.0 Updates `jackson-dataformat-yaml` from 2.14.2 to 2.15.0 - [Commits](https://github.com/FasterXML/jackson-dataformats-text/compare/jackson-dataformats-text-2.14.2...jackson-dataformats-text-2.15.0) --- updated-dependencies: - dependency-name: com.fasterxml.jackson:jackson-bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.module:jackson-module-jaxb-annotations dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.module:jackson-module-parameter-names dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.jaxrs:jackson-jaxrs-base dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jdk8 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de98c5e87f..f27cc97fca 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ limitations under the License. 6.0.2 4.0.0 - 2.14.2 + 2.15.0 2.14 3.41.2.1 21.1.1 From ed60c787578963041c993cf571da1a43de91df9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 11:08:39 +0000 Subject: [PATCH 070/194] Bump spring.security.version from 6.0.2 to 6.0.3 Bumps `spring.security.version` from 6.0.2 to 6.0.3. Updates `spring-security-core` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.0.2...6.0.3) Updates `spring-security-config` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/spring-projects/spring-security/releases) - [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc) - [Commits](https://github.com/spring-projects/spring-security/compare/6.0.2...6.0.3) --- updated-dependencies: - dependency-name: org.springframework.security:spring-security-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.security:spring-security-config dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de98c5e87f..4bbd1ac221 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ limitations under the License. Failure to do this leads to strange misbehaviour in tooltips when editing application.yml --> - 6.0.2 + 6.0.3 4.0.0 2.14.2 From 7751d23f2dbad019eec8897b46a4bb62c9081ada Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 11:08:57 +0000 Subject: [PATCH 071/194] Bump testing.version from 3.0.0 to 3.1.0 Bumps `testing.version` from 3.0.0 to 3.1.0. Updates `maven-surefire-plugin` from 3.0.0 to 3.1.0 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0) Updates `maven-failsafe-plugin` from 3.0.0 to 3.1.0 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de98c5e87f..243695aea9 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ limitations under the License. 5.9.3 10.3.3 3.5.0 - 3.0.0 + 3.1.0 2.0.7 2.20.0 From 92ad8dca5dd65723a412b52c7e06600cd5a865c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 11:09:18 +0000 Subject: [PATCH 072/194] Bump spring.version from 6.0.7 to 6.0.8 Bumps `spring.version` from 6.0.7 to 6.0.8. Updates `spring-framework-bom` from 6.0.7 to 6.0.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.7...v6.0.8) Updates `spring-test` from 6.0.7 to 6.0.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.7...v6.0.8) Updates `spring-webmvc` from 6.0.7 to 6.0.8 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.7...v6.0.8) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de98c5e87f..8615abc29d 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.0.7 2.20.0 - 6.0.7 + 6.0.8 3.0.5 + org.springframework.security + spring-security-bom + ${spring-security.version} + pom + import + org.springframework @@ -288,12 +297,6 @@ limitations under the License. pom import - - - org.springframework - spring-webmvc - ${spring.version} - diff --git a/pom.xml b/pom.xml index 4bbd1ac221..fcd67d4d42 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,13 @@ limitations under the License. pom import + + org.springframework.security + spring-security-bom + ${spring.security.version} + pom + import + org.testcontainers testcontainers-bom @@ -286,16 +293,6 @@ limitations under the License. cxf-rt-frontend-jaxrs ${cxf.version} - - org.springframework.security - spring-security-core - ${spring.security.version} - - - org.springframework.security - spring-security-config - ${spring.security.version} - jakarta.servlet jakarta.servlet-api From 40a9ea74372adc28e25580d2321f58fef229d5ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 14:07:01 +0000 Subject: [PATCH 078/194] Bump spring.version from 6.0.8 to 6.0.9 Bumps `spring.version` from 6.0.8 to 6.0.9. Updates `spring-framework-bom` from 6.0.8 to 6.0.9 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.8...v6.0.9) Updates `spring-test` from 6.0.8 to 6.0.9 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.8...v6.0.9) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1ab46f3034..cdd6e310ef 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.0.7 2.20.0 - 6.0.8 + 6.0.9 3.0.5 6.0.3 - 4.0.0 + 4.0.1 2.15.0 2.14 3.41.2.1 From 0d9b564944f0faf0c4f508c14f3bfaa6e6f770f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 14:07:31 +0000 Subject: [PATCH 082/194] Bump checkstyle from 10.3.3 to 10.11.0 Bumps [checkstyle](https://github.com/checkstyle/checkstyle) from 10.3.3 to 10.11.0. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.3.3...checkstyle-10.11.0) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1ab46f3034..3f78d315f8 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ limitations under the License. 7.0.0-SNAPSHOT 5.9.3 - 10.3.3 + 10.11.0 3.5.0 3.1.0 From 2a97f3797bbfca5cca93805e74302432c9bcb604 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 16 May 2023 08:53:49 +0100 Subject: [PATCH 083/194] Remove change: I'd already solved it on this branch --- SpiNNaker-allocserv/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SpiNNaker-allocserv/pom.xml b/SpiNNaker-allocserv/pom.xml index 8881f91485..7911347eee 100644 --- a/SpiNNaker-allocserv/pom.xml +++ b/SpiNNaker-allocserv/pom.xml @@ -422,11 +422,6 @@ limitations under the License. org.apache.cxf cxf-rt-rs-service-description-openapi-v3 - - - jakarta.xml.ws - jakarta.xml.ws-api - org.webjars swagger-ui From 419c60f737d5c2e8a7e548692a60968f4d6da507 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 07:56:54 +0000 Subject: [PATCH 084/194] Bump spring.boot.version from 3.0.5 to 3.0.6 Bumps `spring.boot.version` from 3.0.5 to 3.0.6. Updates `spring-boot-maven-plugin` from 3.0.5 to 3.0.6 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.5...v3.0.6) Updates `spring-boot-dependencies` from 3.0.5 to 3.0.6 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.5...v3.0.6) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a1c54332e..a7eafca04e 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ limitations under the License. 2.20.0 6.0.9 - 3.0.5 + 3.0.6 - 6.0.3 + 6.1.0 4.0.1 2.15.1 From c28bd388127244a89938e1dccb061dc57d770b1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 09:37:41 +0000 Subject: [PATCH 094/194] Bump jakarta.mail-api from 2.1.1 to 2.1.2 Bumps [jakarta.mail-api](https://github.com/jakartaee/mail-api) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/jakartaee/mail-api/releases) - [Commits](https://github.com/jakartaee/mail-api/compare/2.1.1...2.1.2) --- updated-dependencies: - dependency-name: jakarta.mail:jakarta.mail-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e63178985c..855c93c4a2 100644 --- a/pom.xml +++ b/pom.xml @@ -301,7 +301,7 @@ limitations under the License. jakarta.mail jakarta.mail-api - 2.1.1 + 2.1.2 org.apache.cxf From 305171d75be5e76c90536effce3aaf13d47706c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 09:37:48 +0000 Subject: [PATCH 095/194] Bump jspc-maven-plugin from 4.0.1 to 4.1.1 Bumps [jspc-maven-plugin](https://github.com/leonardehrenfried/jspc-maven-plugin) from 4.0.1 to 4.1.1. - [Release notes](https://github.com/leonardehrenfried/jspc-maven-plugin/releases) - [Commits](https://github.com/leonardehrenfried/jspc-maven-plugin/compare/jspc-maven-plugin-4.0.1...jspc-maven-plugin-4.1.1) --- updated-dependencies: - dependency-name: io.leonard.maven.plugins:jspc-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e63178985c..e5f1ccfb53 100644 --- a/pom.xml +++ b/pom.xml @@ -638,7 +638,7 @@ limitations under the License. io.leonard.maven.plugins jspc-maven-plugin - 4.0.1 + 4.1.1 org.apache.rat From eb79a8530f65c08360f8a69bd9ab1c20cea91857 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:07:09 +0000 Subject: [PATCH 096/194] Bump cxf.version from 4.0.1 to 4.0.2 Bumps `cxf.version` from 4.0.1 to 4.0.2. Updates `cxf-rt-frontend-jaxrs` from 4.0.1 to 4.0.2 Updates `cxf-spring-boot-starter-jaxrs` from 4.0.1 to 4.0.2 Updates `cxf-bom` from 4.0.1 to 4.0.2 --- updated-dependencies: - dependency-name: org.apache.cxf:cxf-rt-frontend-jaxrs dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.cxf:cxf-spring-boot-starter-jaxrs dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.cxf:cxf-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5b25986fc6..8585142399 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ limitations under the License. --> 6.1.0 - 4.0.1 + 4.0.2 2.15.2 2.14 3.42.0.0 From a4e555b69aec785fcd807985ac067dfe4c9ed80b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:05:31 +0000 Subject: [PATCH 097/194] Bump error-prone.version from 2.19.1 to 2.20.0 Bumps `error-prone.version` from 2.19.1 to 2.20.0. Updates `error_prone_annotations` from 2.19.1 to 2.20.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.19.1...v2.20.0) Updates `error_prone_core` from 2.19.1 to 2.20.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.19.1...v2.20.0) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0a90051ea..4576bbf7aa 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ limitations under the License. 4.19.0 1.0.5 2.7.3 - 2.19.1 + 2.20.0 4.7.4 8.0.33 1.18.3 From 480a3c335928c19fadb26e23214212bde5a17f58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:06:00 +0000 Subject: [PATCH 098/194] Bump error-prone.version from 2.19.1 to 2.20.0 Bumps `error-prone.version` from 2.19.1 to 2.20.0. Updates `error_prone_annotations` from 2.19.1 to 2.20.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.19.1...v2.20.0) Updates `error_prone_core` from 2.19.1 to 2.20.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.19.1...v2.20.0) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0cd9d596c..301adecec1 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ limitations under the License. 4.19.0 1.0.5 2.7.3 - 2.19.1 + 2.20.0 4.7.4 8.0.33 1.18.3 From 735543dc188c848b7be5b0f19ba972e5d554ba2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:06:25 +0000 Subject: [PATCH 099/194] Bump spring.version from 6.0.9 to 6.0.10 Bumps `spring.version` from 6.0.9 to 6.0.10. Updates `spring-framework-bom` from 6.0.9 to 6.0.10 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.9...v6.0.10) Updates `spring-test` from 6.0.9 to 6.0.10 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.9...v6.0.10) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0cd9d596c..cc959c77ac 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.0.7 2.20.0 - 6.0.9 + 6.0.10 3.1.0 - 6.1.0 + 6.1.1 4.0.2 2.15.2 From 6f1c1992d4f424580fba613caace65ed2e0a94ac Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 20 Jun 2023 14:33:21 +0100 Subject: [PATCH 101/194] Clean out code that wasn't doing anything --- .../front_end/CommandLineInterface.java | 35 +++++++++---------- .../spinnaker/front_end/dse/BoardWorker.java | 23 ++---------- .../dse/FastExecuteDataSpecification.java | 28 +++++---------- .../dse/HostExecuteDataSpecification.java | 29 ++++----------- 4 files changed, 35 insertions(+), 80 deletions(-) diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java index dc44abf98d..53df41546b 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/CommandLineInterface.java @@ -16,14 +16,13 @@ package uk.ac.manchester.spinnaker.front_end; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toUnmodifiableList; import org.slf4j.Logger; import static org.slf4j.LoggerFactory.getLogger; import static picocli.CommandLine.ExitCode.USAGE; import static uk.ac.manchester.spinnaker.alloc.client.SpallocClientFactory.getJobFromProxyInfo; import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.DOWNLOAD_DESC; import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.DSE_APP_DESC; -import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.DSE_DESC; import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.DSE_MON_DESC; import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.DSE_SYS_DESC; import static uk.ac.manchester.spinnaker.front_end.CommandDescriptions.GATHER_DESC; @@ -711,33 +710,33 @@ private static SpallocClient.Job getJob(DatabaseAPI storage) return getJobFromProxyInfo(storage.getProxyInformation()); } + @MustBeClosed + private static TransceiverInterface makeTxrx(Machine machine, + SpallocClient.Job job) + throws IOException, SpinnmanException, InterruptedException { + if (job != null) { + return job.getTransceiver(); + } + // No job; must be a direct connection + var conns = machine.ethernetConnectedChips().stream() + .map(chip -> new ConnectionDescriptor(chip.ipAddress, + SCP_SCAMP_PORT, chip.asChipLocation())) + .collect(toUnmodifiableList()); + return Transceiver.makeWithDescriptors(machine.version, conns); + } + @MustBeClosed @SuppressWarnings("MustBeClosed") private static TransceiverInterface getTransceiver(Machine machine, SpallocClient.Job job) throws IOException, SpinnmanException, InterruptedException { - final TransceiverInterface txrx; - if (job == null) { - // No job; must be a direct connection - txrx = Transceiver.makeWithDescriptors( - machine.version, generateScampConnections(machine)); - } else { - txrx = job.getTransceiver(); - } + var txrx = makeTxrx(machine, job); var scpSelector = txrx.getScampConnectionSelector(); if (scpSelector instanceof MachineAware ma) { ma.setMachine(machine); } return txrx; } - - private static List generateScampConnections( - Machine machine) { - return machine.ethernetConnectedChips().stream() - .map(chip -> new ConnectionDescriptor(chip.ipAddress, - SCP_SCAMP_PORT, chip.asChipLocation())) - .collect(toList()); - } } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java index ce6158f806..0d0c3df556 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java @@ -15,20 +15,16 @@ */ package uk.ac.manchester.spinnaker.front_end.dse; -import static org.slf4j.LoggerFactory.getLogger; import uk.ac.manchester.spinnaker.machine.CoreLocation; import static uk.ac.manchester.spinnaker.front_end.Constants.CORE_DATA_SDRAM_BASE_TAG; import java.io.IOException; import java.nio.ByteBuffer; -import org.slf4j.Logger; - import static java.nio.ByteBuffer.allocate; import static java.nio.ByteOrder.LITTLE_ENDIAN; import java.util.LinkedHashMap; -import uk.ac.manchester.spinnaker.front_end.Progress; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; import uk.ac.manchester.spinnaker.messages.model.AppID; @@ -40,8 +36,6 @@ import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; abstract class BoardWorker { - private static final Logger log = getLogger(BoardWorker.class); - /** The transceiver for talking to the SpiNNaker machine. */ protected final TransceiverInterface txrx; @@ -51,18 +45,9 @@ abstract class BoardWorker { /** The database holding the DS data.*/ private final DSEStorage storage; - /* The bar to print out if possible.*/ - private final Progress bar; - /** The system wide app id.*/ private final int appId; - /** - * Data spec magic number. This marks the start of a block of memory in - * SpiNNaker's SDRAM that has been allocated by the Data Specification. - */ - private static final int DSG_MAGIC_NUM = 0x5B7CA17E; - /** Application data magic number. */ private static final int APPDATA_MAGIC_NUM = 0xAD130AD6; @@ -111,10 +96,9 @@ abstract class BoardWorker { * If the database access fails. */ protected BoardWorker(TransceiverInterface txrx, Ethernet board, - DSEStorage storage, Progress bar) throws StorageException { + DSEStorage storage) throws StorageException { this.board = board; this.storage = storage; - this.bar = bar; this.appId = storage.getAppId(); this.txrx = txrx; } @@ -149,7 +133,7 @@ protected void mallocCore(CoreLocation xyp) throws txrx.writeUser0(xyp, start); storage.setStartAddress(xyp, start); - int nextPointer = start.address + APP_PTR_TABLE_BYTE_SIZE; + int nextPointer = start.address() + APP_PTR_TABLE_BYTE_SIZE; for (var regionNum : regionSizes.keySet()) { var size = regionSizes.get(regionNum); storage.setRegionPointer(xyp, regionNum, nextPointer); @@ -175,7 +159,6 @@ protected void mallocCore(CoreLocation xyp) throws */ protected void loadCore(CoreLocation xyp) throws IOException, ProcessException, StorageException, InterruptedException { - int totalWritten = APP_PTR_TABLE_BYTE_SIZE; var pointerTable = allocate(APP_PTR_TABLE_BYTE_SIZE).order(LITTLE_ENDIAN); //header @@ -186,7 +169,7 @@ protected void loadCore(CoreLocation xyp) throws IOException, for (int region = 0; region < MAX_MEM_REGIONS; region++) { if (regionInfos.containsKey(region)) { var regionInfo = regionInfos.get(region); - pointerTable.putInt(regionInfo.pointer.address); + pointerTable.putInt(regionInfo.pointer.address()); if (regionInfo.content != null) { var written = writeRegion( xyp, regionInfo.content, regionInfo.pointer); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index f1484502d2..247125a556 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -24,7 +24,6 @@ import static java.util.stream.Collectors.toList; import static java.util.stream.IntStream.range; import static org.slf4j.LoggerFactory.getLogger; -import static uk.ac.manchester.spinnaker.front_end.Constants.CORE_DATA_SDRAM_BASE_TAG; import static uk.ac.manchester.spinnaker.front_end.DebuggingUtils.compareBuffers; import static uk.ac.manchester.spinnaker.front_end.dse.FastDataInProtocol.computeNumPackets; import static uk.ac.manchester.spinnaker.messages.Constants.NBBY; @@ -51,12 +50,7 @@ import com.google.errorprone.annotations.CheckReturnValue; import com.google.errorprone.annotations.MustBeClosed; -import difflib.ChangeDelta; -import difflib.Chunk; -import difflib.DeleteDelta; -import difflib.InsertDelta; import uk.ac.manchester.spinnaker.front_end.NoDropPacketContext; -import uk.ac.manchester.spinnaker.front_end.Progress; import uk.ac.manchester.spinnaker.front_end.download.request.Gather; import uk.ac.manchester.spinnaker.front_end.download.request.Monitor; import uk.ac.manchester.spinnaker.machine.ChipLocation; @@ -86,9 +80,6 @@ public class FastExecuteDataSpecification extends ExecuteDataSpecification { private static final String SPINNAKER_COMPARE_UPLOAD = getProperty("spinnaker.compare.upload"); - private static final String LOADING_MSG = - "loading data specifications onto SpiNNaker"; - private static final String IN_REPORT_NAME = "speeds_gained_in_speed_up_process.tsv"; @@ -216,15 +207,12 @@ public void loadCores() InterruptedException { var storage = db.getStorageInterface(); var ethernets = storage.listEthernetsToLoad(); - int opsToRun = storage.countCores(false); - try (var bar = new Progress(opsToRun, LOADING_MSG)) { - processTasksInParallel(ethernets, board -> { - return () -> loadBoard(board, storage, bar); - }); - } + processTasksInParallel(ethernets, board -> { + return () -> loadBoard(board, storage); + }); } - private void loadBoard(Ethernet board, DSEStorage storage, Progress bar) + private void loadBoard(Ethernet board, DSEStorage storage) throws IOException, ProcessException, StorageException, InterruptedException { var cores = storage.listCoresToLoad(board, false); @@ -235,7 +223,7 @@ private void loadBoard(Ethernet board, DSEStorage storage, Progress bar) log.info("loading data onto {} cores on board", cores.size()); var gather = gathererForChip.get(board.location); try (var worker = new FastBoardWorker( - txrx, board, storage, gather, bar)) { + txrx, board, storage, gather)) { for (var xyp : cores) { worker.mallocCore(xyp); } @@ -332,10 +320,10 @@ private class FastBoardWorker extends BoardWorker implements AutoCloseable { @MustBeClosed @SuppressWarnings("MustBeClosed") FastBoardWorker(TransceiverInterface txrx, Ethernet board, - DSEStorage storage, Gather gather, Progress bar) + DSEStorage storage, Gather gather) throws IOException, ProcessException, InterruptedException, StorageException { - super(txrx, board, storage, bar); + super(txrx, board, storage); this.logContext = new BoardLocal(board.location); this.connection = new ThrottledConnection(txrx, board, gather.getIptag()); @@ -438,7 +426,7 @@ protected int writeRegion(HasCoreLocation core, ByteBuffer content, if (SPINNAKER_COMPARE_UPLOAD != null) { var readBack = txrx.readMemory( core, baseAddress, content.remaining()); - compareBuffers(content, readBack); + compareBuffers(content, readBack, log); } return written; } diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java index 4b641b2864..10fcb45b49 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/HostExecuteDataSpecification.java @@ -15,17 +15,12 @@ */ package uk.ac.manchester.spinnaker.front_end.dse; -import static org.slf4j.LoggerFactory.getLogger; - import java.io.IOException; import java.net.URISyntaxException; import java.nio.ByteBuffer; -import org.slf4j.Logger; - import com.google.errorprone.annotations.MustBeClosed; -import uk.ac.manchester.spinnaker.front_end.Progress; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.Machine; import uk.ac.manchester.spinnaker.machine.MemoryLocation; @@ -42,12 +37,6 @@ * @author Donal Fellows */ public class HostExecuteDataSpecification extends ExecuteDataSpecification { - private static final String LOADING_MSG = - "loading data specifications onto SpiNNaker"; - - private static final Logger log = - getLogger(HostExecuteDataSpecification.class); - /** * Create a high-level DSE interface. * @@ -105,20 +94,16 @@ public void loadCores(boolean system) InterruptedException { var storage = db.getStorageInterface(); var ethernets = storage.listEthernetsToLoad(); - int opsToRun = storage.countCores(system); - try (var bar = new Progress(opsToRun, LOADING_MSG)) { - processTasksInParallel(ethernets, board -> { - return () -> loadBoard(board, storage, bar, system); - }); - } + processTasksInParallel(ethernets, board -> { + return () -> loadBoard(board, storage, system); + }); } - private void loadBoard(Ethernet board, DSEStorage storage, Progress bar, - boolean system) + private void loadBoard(Ethernet board, DSEStorage storage, boolean system) throws IOException, ProcessException, StorageException, InterruptedException { try (var c = new BoardLocal(board.location)) { - var worker = new HostBoardWorker(txrx, board, storage, bar); + var worker = new HostBoardWorker(txrx, board, storage); for (var xyp : storage.listCoresToLoad(board, system)) { worker.mallocCore(xyp); } @@ -130,8 +115,8 @@ private void loadBoard(Ethernet board, DSEStorage storage, Progress bar, private class HostBoardWorker extends BoardWorker { HostBoardWorker(TransceiverInterface txrx, Ethernet board, - DSEStorage storage, Progress bar) throws StorageException { - super(txrx, board, storage, bar); + DSEStorage storage) throws StorageException { + super(txrx, board, storage); } @Override From 58de4b6898ec0b909fb9801826dedff5c2a3c08e Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 20 Jun 2023 14:44:44 +0100 Subject: [PATCH 102/194] Tidy up after merge --- .../main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java index 7f4034ddd7..3d5206360b 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/DSEStorage.java @@ -20,7 +20,6 @@ import java.util.Map; import jakarta.validation.Valid; -import jakarta.validation.constraints.Positive; import uk.ac.manchester.spinnaker.machine.ChipLocation; import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; From 7588be75ce7b936c7b8de0d5196ae0b6fad41a0c Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Tue, 20 Jun 2023 16:40:56 +0100 Subject: [PATCH 103/194] Tidy up to use Java 17 idioms --- .../dse/FastExecuteDataSpecification.java | 3 +- .../storage/sqlite/SQLiteDataSpecStorage.java | 57 +++++++++---------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java index 3d0a4962f4..6a3bd7bf9f 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastExecuteDataSpecification.java @@ -224,8 +224,7 @@ private void loadBoard(Ethernet board, DSEStorage storage) } log.info("loading data onto {} cores on board", cores.size()); var gather = gathererForChip.get(board.location); - try (var worker = new FastBoardWorker( - txrx, board, storage, gather)) { + try (var worker = new FastBoardWorker(txrx, board, storage, gather)) { for (var xyp : cores) { worker.mallocCore(xyp); } diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index fbd66ee8f4..2224a9eb64 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -15,8 +15,18 @@ */ package uk.ac.manchester.spinnaker.storage.sqlite; -import java.nio.ByteBuffer; import static java.nio.ByteBuffer.wrap; +import static java.util.Objects.nonNull; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_APP_ID; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_REGION_POINTER_AND_CONTEXT; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_REGION_SIZES; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_START_ADDRESS; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.LIST_CORES_TO_LOAD; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.LIST_ETHERNETS; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_REGION_POINTER; +import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_START_ADDRESS; + +import java.nio.ByteBuffer; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; @@ -26,16 +36,6 @@ import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; - -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_APP_ID; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_REGION_POINTER_AND_CONTEXT; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_REGION_SIZES; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.GET_START_ADDRESS; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.LIST_ETHERNETS; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_REGION_POINTER; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_START_ADDRESS; -import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.LIST_CORES_TO_LOAD; - import uk.ac.manchester.spinnaker.storage.DSEDatabaseEngine; import uk.ac.manchester.spinnaker.storage.DSEStorage; import uk.ac.manchester.spinnaker.storage.RegionInfo; @@ -143,35 +143,37 @@ public HashMap getRegionPointersAndContent( private static HashMap getRegionPointersAndContent( Connection conn, CoreLocation xyp) throws SQLException { - HashMap results = - new HashMap(); try (var s = conn.prepareStatement(GET_REGION_POINTER_AND_CONTEXT)) { // x, y, p setArguments(s, xyp.getX(), xyp.getY(), xyp.getP()); try (var rs = s.executeQuery()) { + var results = new HashMap(); while (rs.next()) { - ByteBuffer content = null; - if (rs.getBytes("content") != null) { - content = - wrap(rs.getBytes("content")).asReadOnlyBuffer(); - } - var info = new RegionInfo( - content, new MemoryLocation(rs.getInt("pointer"))); - results.put(rs.getInt("region_num"), info); + results.put(rs.getInt("region_num"), + new RegionInfo( + wrapIfNotNull(rs.getBytes("content")), + new MemoryLocation(rs.getInt("pointer")))); } + return results; } - return results; } } + private static ByteBuffer wrapIfNotNull(byte[] buffer) { + if (nonNull(buffer)) { + return wrap(buffer).asReadOnlyBuffer(); + } + return null; + } + @Override public void setStartAddress(CoreLocation xyp, MemoryLocation start) throws StorageException { - callV(conn -> setStartAddres(conn, xyp, start), + callV(conn -> setStartAddress(conn, xyp, start), "saving data loading metadata"); } - private static void setStartAddres(Connection conn, + private static void setStartAddress(Connection conn, CoreLocation xyp, MemoryLocation start) throws SQLException { try (var s = conn.prepareStatement(SET_START_ADDRESS)) { // start_address, x, y, p @@ -247,11 +249,8 @@ private EthernetImpl(int etherx, int ethery, String addr) { @Override public boolean equals(Object other) { - if (!(other instanceof EthernetImpl)) { - return false; - } - var b = (EthernetImpl) other; - return location == b.location; + return (other instanceof EthernetImpl b) + && (location == b.location); } @Override From dffdfe2da62c45853766516e51f4009764e104d6 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 21 Jun 2023 14:30:15 +0100 Subject: [PATCH 104/194] Cleaning up byte buffer handling, more sealed classes --- .../spinnaker/alloc/bmp/FirmwareLoader.java | 7 +-- .../spinnaker/alloc/proxy/ProxyCore.java | 8 ++-- .../alloc/proxy/ProxyUDPConnection.java | 5 +- .../spinnaker/alloc/bmp/MockTransceiver.java | 6 +-- .../spinnaker/alloc/client/ClientSession.java | 4 +- .../spinnaker/alloc/client/ProxyProtocol.java | 4 +- .../connections/NotificationConnection.java | 14 +----- .../spinnaker/connections/UDPConnection.java | 11 ++--- .../manchester/spinnaker/messages/Utils.java | 45 ----------------- .../spinnaker/messages/bmp/BMPRequest.java | 22 +++++++-- .../spinnaker/messages/bmp/ReadBMPMemory.java | 4 +- .../messages/bmp/ReadSerialFlash.java | 4 +- .../messages/bmp/WriteFPGARegister.java | 2 +- .../spinnaker/messages/boot/BootMessages.java | 4 +- .../messages/eieio/AbstractDataElement.java | 3 +- .../messages/eieio/CustomEIEIOCommand.java | 4 +- .../messages/eieio/EIEIOCommand.java | 3 +- .../messages/eieio/EIEIOCommandMessage.java | 9 ++-- .../messages/eieio/EIEIODataMessage.java | 10 ++-- .../spinnaker/messages/eieio/EIEIOHeader.java | 3 +- .../messages/eieio/EIEIOMessage.java | 4 +- .../spinnaker/messages/model/Blacklist.java | 8 ++-- .../spinnaker/messages/model/ChipInfo.java | 4 +- .../spinnaker/messages/model/IOBuffer.java | 6 +-- .../spinnaker/messages/scp/FECRequest.java | 2 +- .../spinnaker/messages/scp/IPTagGetInfo.java | 2 +- .../messages/scp/PayloadedResponse.java | 9 +++- .../spinnaker/messages/scp/ReadLink.java | 4 +- .../spinnaker/messages/scp/ReadMemory.java | 4 +- .../spinnaker/messages/sdp/SDPMessage.java | 4 +- .../spinnaker/transceiver/Accumulator.java | 4 +- .../transceiver/BMPTransceiverInterface.java | 8 ++-- .../spinnaker/transceiver/FillProcess.java | 5 +- .../MulticastRoutesControlProcess.java | 5 +- .../transceiver/RuntimeControlProcess.java | 5 +- .../transceiver/TransceiverInterface.java | 2 +- .../spinnaker/transceiver/Utils.java | 5 +- .../spinnaker/messages/model/TestCpuInfo.java | 6 +-- .../messages/model/TestVersionInfo.java | 7 ++- .../messages/scp/TestCountState.java | 7 ++- .../messages/scp/TestOKResponse.java | 10 ++-- .../spinnaker/messages/scp/TestVersion.java | 9 ++-- .../transceiver/TransceiverITCase.java | 7 ++- .../front_end/download/ClearMessage.java | 5 +- .../MissingSequenceNumbersMessage.java | 5 +- .../download/StartSendingMessage.java | 5 +- .../spinnaker/front_end/dse/BoardWorker.java | 12 ++--- .../front_end/dse/FastDataInProtocol.java | 9 ++-- .../storage/sqlite/SQLiteDataSpecStorage.java | 3 +- .../spinnaker/utils/ByteBufferUtils.java | 48 +++++++++++++------ .../spinnaker/utils/TestByteBufferUtils.java | 14 +++--- 51 files changed, 182 insertions(+), 218 deletions(-) delete mode 100644 SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/Utils.java 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 5a0082b7c6..015732c184 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 @@ -35,6 +35,8 @@ 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.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; @@ -183,8 +185,7 @@ 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); } } @@ -220,7 +221,7 @@ private static class FlashDataSector { final ByteBuffer buf; FlashDataSector() { - buf = ByteBuffer.allocate(DATA_SECTOR_LENGTH).order(LITTLE_ENDIAN); + buf = alloc(DATA_SECTOR_LENGTH); } static FlashDataSector registers(int numItems, List data) { 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 a7ffe044a1..99e46c9a06 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; @@ -184,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; @@ -210,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); 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 389398f8a6..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); 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 eaadaf0ec4..2a68281809 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,13 +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; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import static uk.ac.manchester.spinnaker.utils.UnitConstants.MEGABYTE; import java.io.IOException; @@ -119,7 +119,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); @@ -184,7 +184,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; } 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 8417c9bab7..ac6c324127 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 @@ -430,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)); } /** 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/connections/NotificationConnection.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/connections/NotificationConnection.java index 229996e40b..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,13 +15,11 @@ */ 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.NotificationMessage; @@ -93,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. * @@ -111,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); 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 f6eba3ee85..4a4165b53b 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/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 ad5a61cb8e..f61217ab91 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 @@ -40,8 +40,13 @@ * @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 BMPLocation(board), DEFAULT_PORT); @@ -196,7 +201,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. * @@ -222,8 +228,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/ReadBMPMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.java index eddc9a5cd9..df5eac5e6b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadBMPMemory.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; @@ -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/ReadSerialFlash.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/ReadSerialFlash.java index 77b6e98ff8..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; @@ -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/WriteFPGARegister.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/bmp/WriteFPGARegister.java index c81082c5c2..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; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java index f444712679..b38276abc4 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/boot/BootMessages.java @@ -21,7 +21,6 @@ import static java.lang.System.currentTimeMillis; import static java.nio.ByteBuffer.allocate; import static java.nio.ByteOrder.BIG_ENDIAN; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.util.stream.IntStream.range; import static java.util.stream.Stream.concat; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; @@ -29,6 +28,7 @@ import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.boot_signature; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.is_root_chip; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.unix_timestamp; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import static uk.ac.manchester.spinnaker.utils.UnitConstants.KILOBYTE; import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC; @@ -93,7 +93,7 @@ private BootMessages(SystemVariableBootValues bootVariables, private void injectBootVariableBlock( SystemVariableBootValues bootVariables) { // NB: Endian shenanigans! - var buffer = allocate(BOOT_VARIABLE_SIZE).order(LITTLE_ENDIAN); + var buffer = alloc(BOOT_VARIABLE_SIZE); bootVariables.addToBuffer(buffer); buffer.position(0); for (int i = 0; i < BOOT_STRUCT_REPLACE_LENGTH / WORD_SIZE; i++) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/AbstractDataElement.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/AbstractDataElement.java index 97d19f3187..7bd1663f4c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/AbstractDataElement.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/AbstractDataElement.java @@ -20,7 +20,8 @@ /** * A marker interface for possible data elements in the EIEIO data packet. */ -public interface AbstractDataElement { +public sealed interface AbstractDataElement + permits KeyDataElement, KeyPayloadDataElement { /** * Writes this message chunk into the given buffer. This is so that a * message can be sent. diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/CustomEIEIOCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/CustomEIEIOCommand.java index 26eceba051..0562813f73 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/CustomEIEIOCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/CustomEIEIOCommand.java @@ -21,7 +21,7 @@ * @see EIEIOCommandID#get(int) * @author Donal Fellows */ -public class CustomEIEIOCommand implements EIEIOCommand { +public final class CustomEIEIOCommand implements EIEIOCommand { // Must be power of 2 (minus 1) private static final int MAX_COMMAND = 0x3FFF; @@ -30,6 +30,8 @@ public class CustomEIEIOCommand implements EIEIOCommand { /** * @param command * The ID value of the command. + * @throws IllegalArgumentException + * If the command ID is negative or too large. */ CustomEIEIOCommand(int command) { if (command < 0 || command > MAX_COMMAND) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommand.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommand.java index e48e5f6ee4..02a6d01b77 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommand.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommand.java @@ -21,7 +21,8 @@ * * @author Donal Fellows */ -public interface EIEIOCommand { +public sealed interface EIEIOCommand + permits EIEIOCommandID, CustomEIEIOCommand { /** * Get the encoded ID number of the command. * diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommandMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommandMessage.java index fa9471423e..52a7d750c6 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommandMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOCommandMessage.java @@ -27,8 +27,11 @@ * @author Sergio Davies * @author Donal Fellows */ -public class EIEIOCommandMessage - implements EIEIOMessage { +public sealed class EIEIOCommandMessage + implements EIEIOMessage + permits EventStopRequest, HostDataRead, HostDataReadAck, + HostSendSequencedData, PaddingRequest, SpinnakerRequestBuffers, + SpinnakerRequestReadData, StartRequests, StopRequests { // Must be power of 2 (minus 1) private static final int MAX_COMMAND = 0x3FFF; @@ -75,7 +78,7 @@ public Header getHeader() { } /** EIEIO header for command packets. */ - public static class Header implements EIEIOHeader { + public static final class Header implements EIEIOHeader { /** The command ID in this header. */ public final EIEIOCommand command; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java index 95146d2ee3..1bb1b6b0bf 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIODataMessage.java @@ -19,11 +19,11 @@ import static java.lang.Math.floorDiv; import static java.lang.Short.toUnsignedInt; import static java.lang.String.format; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.util.Collections.emptyIterator; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; import static uk.ac.manchester.spinnaker.messages.eieio.EIEIOPrefix.LOWER_HALF_WORD; import static uk.ac.manchester.spinnaker.transceiver.Utils.newMessageBuffer; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.nio.ByteBuffer; import java.util.Iterator; @@ -65,7 +65,7 @@ public EIEIODataMessage(EIEIOType eieioType) { EIEIODataMessage(ByteBuffer data) { this.header = new Header(data); this.elements = null; - this.data = data.asReadOnlyBuffer().order(LITTLE_ENDIAN); + this.data = readOnly(data); } /** @@ -168,7 +168,7 @@ public void addKey(int key) { /** @return The raw data of this message. */ public ByteBuffer getData() { - return data.asReadOnlyBuffer().order(LITTLE_ENDIAN); + return readOnly(data); } /** @@ -204,7 +204,7 @@ public Iterator iterator() { return emptyIterator(); } - final var d = data.duplicate().order(LITTLE_ENDIAN); + final var d = readOnly(data); return new Iterator() { private int elementsRead = 0; @@ -251,7 +251,7 @@ public Header getHeader() { } /** EIEIO header for data packets. */ - public static class Header implements EIEIOHeader { + public static final class Header implements EIEIOHeader { /** The type of packet (size of various fields). */ public final EIEIOType eieioType; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOHeader.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOHeader.java index 63f2431869..bb5043427b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOHeader.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOHeader.java @@ -22,5 +22,6 @@ * * @author Donal Fellows */ -public interface EIEIOHeader extends SerializableMessage { +public sealed interface EIEIOHeader extends SerializableMessage + permits EIEIOCommandMessage.Header, EIEIODataMessage.Header { } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessage.java index c9cabe373c..9ee8ca9a4b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/eieio/EIEIOMessage.java @@ -23,8 +23,8 @@ * @param

* The type of header on this message. */ -public interface EIEIOMessage
- extends SerializableMessage { +public sealed interface EIEIOMessage
extends + SerializableMessage permits EIEIOCommandMessage, EIEIODataMessage { /** @return the header of this message. */ Header getHeader(); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index 2a0717e6ad..11885c4b69 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -16,7 +16,6 @@ package uk.ac.manchester.spinnaker.messages.model; import static java.lang.Integer.parseInt; -import static java.nio.ByteBuffer.allocate; import static java.nio.ByteBuffer.wrap; import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.nio.charset.StandardCharsets.UTF_8; @@ -38,6 +37,8 @@ import static uk.ac.manchester.spinnaker.machine.MachineDefaults.SIZE_Y_OF_ONE_BOARD; import static uk.ac.manchester.spinnaker.machine.SpiNNakerTriadGeometry.getSpinn5Geometry; 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.ByteBufferUtils.readOnly; import static uk.ac.manchester.spinnaker.utils.CollectionUtils.OR; import static uk.ac.manchester.spinnaker.utils.CollectionUtils.toEnumSet; @@ -159,8 +160,7 @@ public Blacklist(Set deadChips, } private ByteBuffer encodeBlacklist() { - var buf = allocate((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE) - .order(LITTLE_ENDIAN); + var buf = alloc((SPINN5_CHIPS_PER_BOARD + 1) * WORD_SIZE); buf.putInt(0); // Size; filled in later int count = 0; for (int x = 0; x < SIZE_X_OF_ONE_BOARD; x++) { @@ -487,7 +487,7 @@ public boolean isChipMentioned(ChipLocation chip) { /** @return The raw blacklist data in little-endian form. Read only. */ public ByteBuffer getRawData() { - return rawData.asReadOnlyBuffer().order(LITTLE_ENDIAN); + return readOnly(rawData); } @Override diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java index 8e9299c4a5..db09bb3b7e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ChipInfo.java @@ -17,7 +17,6 @@ import static java.lang.Byte.toUnsignedInt; import static java.net.InetAddress.getByAddress; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.util.Collections.sort; import static java.util.Collections.unmodifiableList; import static uk.ac.manchester.spinnaker.messages.model.DataType.ADDRESS; @@ -99,6 +98,7 @@ import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.x_size; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.y; import static uk.ac.manchester.spinnaker.messages.model.SystemVariableDefinition.y_size; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.net.InetAddress; import java.net.UnknownHostException; @@ -151,7 +151,7 @@ public final class ChipInfo implements HasChipLocation { * The data retrieved from SDRAM on the board. */ public ChipInfo(ByteBuffer systemData) { - this.systemData = systemData.asReadOnlyBuffer().order(LITTLE_ENDIAN); + this.systemData = readOnly(systemData); int links = read(links_available); linksAvailable = BitSet.valueOf(new byte[] { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java index c8d5b41776..58836ecb70 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/IOBuffer.java @@ -16,8 +16,8 @@ package uk.ac.manchester.spinnaker.messages.model; import static java.nio.ByteBuffer.wrap; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.nio.charset.StandardCharsets.US_ASCII; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -57,7 +57,7 @@ public IOBuffer(HasCoreLocation core, byte[] contents) { public IOBuffer(HasCoreLocation core, ByteBuffer contents) { this.core = core; iobuf = new byte[contents.remaining()]; - contents.asReadOnlyBuffer().order(LITTLE_ENDIAN).get(iobuf); + readOnly(contents).get(iobuf); } /** @@ -108,7 +108,7 @@ public InputStream getContentsStream() { * buffer. */ public ByteBuffer getContentsBuffer() { - return wrap(iobuf).asReadOnlyBuffer().order(LITTLE_ENDIAN); + return readOnly(wrap(iobuf)); } /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java index 8c8bbb8c6b..b48d97381a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/FECRequest.java @@ -15,10 +15,10 @@ */ package uk.ac.manchester.spinnaker.messages.scp; -import static uk.ac.manchester.spinnaker.messages.Utils.wordAsBuffer; import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_EXPECTED; 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.wordAsBuffer; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java index 02900fb917..1020fdbecb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/IPTagGetInfo.java @@ -51,7 +51,7 @@ public IPTagGetInfo(HasChipLocation chip) { @Override public Response getSCPResponse(ByteBuffer buffer) throws UnexpectedResponseCodeException { - return new IPTagGetInfo.Response(buffer); + return new Response(buffer); } /** An SCP response to a request for information about IP tags. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java index 3982a16723..c845e437cb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/PayloadedResponse.java @@ -31,8 +31,13 @@ * @param * The type of exception thrown by the payload parser. */ -public abstract class PayloadedResponse - extends CheckOKResponse implements Supplier { +public abstract sealed class PayloadedResponse + extends CheckOKResponse implements Supplier + permits CountState.Response, FixedRouteRead.Response, + GetChipInfo.Response, GetReinjectionStatus.Response, + GetVersion.Response, IPTagGet.Response, IPTagGetInfo.Response, + IPTagSetTTO.Response, ReadLink.Response, ReadMemory.Response, + RouterAlloc.Response, SDRAMAlloc.Response, SDRAMDeAlloc.Response { private final T value; PayloadedResponse(String operation, Enum command, ByteBuffer buffer) diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java index e280b33641..111a8ef756 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadLink.java @@ -15,9 +15,9 @@ */ package uk.ac.manchester.spinnaker.messages.scp; -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.scp.SCPCommand.CMD_LINK_READ; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.nio.ByteBuffer; @@ -95,7 +95,7 @@ protected final class Response /** @return The data read, as a read-only little-endian 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/scp/ReadMemory.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java index 3ba6ab419d..15361ea313 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/scp/ReadMemory.java @@ -15,10 +15,10 @@ */ package uk.ac.manchester.spinnaker.messages.scp; -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; @@ -88,7 +88,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/sdp/SDPMessage.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPMessage.java index 89009c9e25..653d51bc8d 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPMessage.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/sdp/SDPMessage.java @@ -17,7 +17,7 @@ import static java.nio.ByteBuffer.allocate; import static java.nio.ByteBuffer.wrap; -import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.nio.ByteBuffer; @@ -131,6 +131,6 @@ public final ByteBuffer getData() { } else { buffer = allocate(0); } - return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN); + return readOnly(buffer); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Accumulator.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Accumulator.java index 680c14dd70..77d7a71e66 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Accumulator.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Accumulator.java @@ -18,7 +18,7 @@ import static java.lang.Math.max; import static java.nio.ByteBuffer.allocate; import static java.nio.ByteBuffer.wrap; -import static java.nio.ByteOrder.LITTLE_ENDIAN; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.io.IOException; import java.io.RandomAccessFile; @@ -109,7 +109,7 @@ public ByteBuffer finish() { done = true; buffer.limit(maxpos); } - return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN); + return readOnly(buffer); } } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java index 268b7cc57d..2892832dec 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPTransceiverInterface.java @@ -16,11 +16,8 @@ package uk.ac.manchester.spinnaker.transceiver; import static java.lang.Thread.interrupted; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.machine.MemoryLocation.NULL; 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.model.PowerCommand.POWER_OFF; import static uk.ac.manchester.spinnaker.messages.model.PowerCommand.POWER_ON; import static uk.ac.manchester.spinnaker.transceiver.BMPConstants.BLACKLIST_BLANK; @@ -32,6 +29,8 @@ import static uk.ac.manchester.spinnaker.transceiver.BMPConstants.SF_BL_LEN; import static uk.ac.manchester.spinnaker.transceiver.Utils.crc; import static uk.ac.manchester.spinnaker.transceiver.Utils.fill; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.wordAsBuffer; import java.io.File; import java.io.IOException; @@ -1520,8 +1519,7 @@ default void writeBlacklist(@Valid BMPCoords bmp, @Valid BMPBoard board, interrupted(); // Prepare the boot data - var data = allocate(BMP_BOOT_SECTOR_SIZE); - data.order(LITTLE_ENDIAN); + var data = alloc(BMP_BOOT_SECTOR_SIZE); data.put(readBMPMemory(bmp, board, BMP_BOOT_SECTOR_ADDR, BMP_BOOT_SECTOR_SIZE)); fill(data, BMP_BOOT_BLACKLIST_OFFSET, SF_BL_LEN, BLACKLIST_BLANK); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java index 7f7e59014f..f3eec1c0b3 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/FillProcess.java @@ -16,10 +16,9 @@ package uk.ac.manchester.spinnaker.transceiver; import static java.lang.String.format; -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.messages.Constants.WORD_SIZE; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.IOException; import java.nio.ByteBuffer; @@ -99,7 +98,7 @@ void fillMemory(HasChipLocation chip, MemoryLocation baseAddress, int data, } // Get a word of data regardless of the type - var buffer = allocate(TWO_WORDS).order(LITTLE_ENDIAN); + var buffer = alloc(TWO_WORDS); while (buffer.hasRemaining()) { dataType.writeTo(data, buffer); } diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/MulticastRoutesControlProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/MulticastRoutesControlProcess.java index 38aad54997..bc5fddf491 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/MulticastRoutesControlProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/MulticastRoutesControlProcess.java @@ -17,11 +17,10 @@ import static java.lang.Byte.toUnsignedInt; import static java.lang.Integer.toUnsignedLong; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.machine.MachineDefaults.ROUTER_AVAILABLE_ENTRIES; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.ROUTING_TABLE_DATA; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.IOException; import java.nio.ByteBuffer; @@ -89,7 +88,7 @@ class MulticastRoutesControlProcess extends WriteMemoryProcess { * @return A buffer big enough to hold everything. */ private static ByteBuffer allocateBuffer(int entries) { - return allocate(BYTES_PER_ENTRY * (entries + 1)).order(LITTLE_ENDIAN); + return alloc(BYTES_PER_ENTRY * (entries + 1)); } private static void writeEntryToBuffer(ByteBuffer buffer, short index, diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java index 617b16b669..4c0ee5e262 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/RuntimeControlProcess.java @@ -16,12 +16,11 @@ package uk.ac.manchester.spinnaker.transceiver; import static java.lang.Math.min; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.util.Objects.requireNonNull; import static uk.ac.manchester.spinnaker.messages.Constants.CPU_IOBUF_ADDRESS_OFFSET; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; import static uk.ac.manchester.spinnaker.transceiver.Utils.getVcpuAddress; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.IOException; import java.nio.ByteBuffer; @@ -262,7 +261,7 @@ private void issueReadForIOBufHead(CoreLocation core, int blockID, private int saveIOBufHead(NextRead read, ByteBuffer bytes, int bytesToRead) { // Create a buffer for the data - var buffer = allocate(bytesToRead).order(LITTLE_ENDIAN); + var buffer = alloc(bytesToRead); // Put the data from this packet into the buffer int packetBytes = min(bytes.remaining(), bytesToRead); if (packetBytes > 0) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java index 0f55ce9c25..21a7777f47 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TransceiverInterface.java @@ -26,7 +26,6 @@ import static uk.ac.manchester.spinnaker.messages.Constants.NO_ROUTER_DIAGNOSTIC_FILTERS; import static uk.ac.manchester.spinnaker.messages.Constants.UDP_MESSAGE_MAX_SIZE; 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.model.AppID.DEFAULT; import static uk.ac.manchester.spinnaker.messages.model.CPUState.READY; import static uk.ac.manchester.spinnaker.messages.model.CPUState.RUN_TIME_EXCEPTION; @@ -37,6 +36,7 @@ import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.SYS_VARS; import static uk.ac.manchester.spinnaker.transceiver.FillDataType.WORD; import static uk.ac.manchester.spinnaker.transceiver.Utils.getVcpuAddress; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.wordAsBuffer; import java.io.File; import java.io.IOException; diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java index 08c494702a..672fb87e49 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/Utils.java @@ -15,10 +15,9 @@ */ package uk.ac.manchester.spinnaker.transceiver; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.messages.Constants.CPU_INFO_BYTES; import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.CPU_INFO; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.IOException; import java.net.InetAddress; @@ -117,7 +116,7 @@ public static void sendPortTriggerMessage(UDPConnection connection, */ public static ByteBuffer newMessageBuffer() { // TODO How big should this buffer be? 256 or (256 + header size)? - return allocate(SPINNAKER_MESSAGE_BUFFER_SIZE).order(LITTLE_ENDIAN); + return alloc(SPINNAKER_MESSAGE_BUFFER_SIZE); } /** diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestCpuInfo.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestCpuInfo.java index f2b4d4440c..657f79f701 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestCpuInfo.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestCpuInfo.java @@ -15,20 +15,18 @@ */ package uk.ac.manchester.spinnaker.messages.model; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static org.junit.jupiter.api.Assertions.*; -import java.nio.ByteBuffer; - import org.junit.jupiter.api.Test; import uk.ac.manchester.spinnaker.machine.CoreLocation; +import uk.ac.manchester.spinnaker.utils.ByteBufferUtils; class TestCpuInfo { @Test void testCreateWithBlankBuffer() { - var b = ByteBuffer.allocate(256).order(LITTLE_ENDIAN); + var b = ByteBufferUtils.alloc(256); var c = new CPUInfo(new CoreLocation(0, 0, 0), b); assertEquals(0, c.getApplicationMailboxDataAddress()); } diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersionInfo.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersionInfo.java index 2e4bc1253b..dd246199c8 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersionInfo.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/model/TestVersionInfo.java @@ -15,9 +15,8 @@ */ package uk.ac.manchester.spinnaker.messages.model; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static org.junit.jupiter.api.Assertions.*; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; @@ -29,7 +28,7 @@ class TestVersionInfo { private ByteBuffer packVersionData(int arg1, int arg2, int arg3, byte[] data) { - var buffer = allocate(25).order(LITTLE_ENDIAN); + var buffer = alloc(25); buffer.putInt(arg1).putInt(arg2).putInt(arg3).put(data).flip(); return buffer; } @@ -93,7 +92,7 @@ void testInvalidSizedVersionData() throws UnsupportedEncodingException { var data = "my/spinnaker".getBytes("ASCII"); // Oh arg3, where art thou? - var versionData = allocate(21).order(LITTLE_ENDIAN); + var versionData = alloc(21); versionData.putInt(arg1).putInt(arg2)/*.putInt(arg3)*/.put(data).flip(); assertThrows(IllegalArgumentException.class, () -> { diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestCountState.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestCountState.java index b6f6dc88e9..35c6fcdae1 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestCountState.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestCountState.java @@ -15,9 +15,8 @@ */ package uk.ac.manchester.spinnaker.messages.scp; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static org.junit.jupiter.api.Assertions.*; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.UnsupportedEncodingException; @@ -54,7 +53,7 @@ void testNewStateResponse() throws UnexpectedResponseCodeException { int srcX = 0x7; int srcY = 0x0; - var data = allocate(18).order(LITTLE_ENDIAN).putShort(PADDING); + var data = alloc(18).putShort(PADDING); data.put(flags.value); data.put((byte) tag); data.put((byte) destPortCPU); @@ -95,7 +94,7 @@ void testFailedDeserialise() throws UnsupportedEncodingException { byte srcX = 0x7; byte srcY = 0x0; - var data = allocate(41).order(LITTLE_ENDIAN).putShort(PADDING); + var data = alloc(41).putShort(PADDING); data.put(flags.value).put(tag).put(destPortCPU).put(srcPortCPU); data.put(destY).put(destX).put(srcY).put(srcX); data.putShort(rc.value).putShort(seq).putShort(p2pAddr); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestOKResponse.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestOKResponse.java index c7e2c27020..f075ada573 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestOKResponse.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestOKResponse.java @@ -15,10 +15,7 @@ */ package uk.ac.manchester.spinnaker.messages.scp; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_DPRI; import static uk.ac.manchester.spinnaker.messages.scp.SCPResult.RC_OK; import static uk.ac.manchester.spinnaker.messages.scp.SCPResult.RC_TIMEOUT; @@ -27,6 +24,7 @@ import org.junit.jupiter.api.Test; import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; +import uk.ac.manchester.spinnaker.utils.ByteBufferUtils; class TestOKResponse { private static final short PADDING = 0; @@ -60,7 +58,7 @@ void testReadOKResponse() throws UnexpectedResponseCodeException { short srcXYShort = (short) (srcX << 8 | srcY); short seq = 103; - var bytes = allocate(14).order(LITTLE_ENDIAN).putShort(PADDING); + var bytes = ByteBufferUtils.alloc(14).putShort(PADDING); bytes.putShort(flagTagShort).putShort(destSourceShort); bytes.putShort(destXYShort).putShort(srcXYShort); bytes.putShort(result).putShort(seq).flip(); @@ -93,7 +91,7 @@ void testNotOKResponse() { short srcXYShort = (short) (srcX << 8 | srcY); short seq = 103; - var bytes = allocate(14).order(LITTLE_ENDIAN).putShort(PADDING); + var bytes = ByteBufferUtils.alloc(14).putShort(PADDING); bytes.putShort(flagTagShort).putShort(destSourceShort); bytes.putShort(destXYShort).putShort(srcXYShort); bytes.putShort(result).putShort(seq).flip(); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestVersion.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestVersion.java index 18670b9036..e4f3c2c7ab 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestVersion.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/messages/scp/TestVersion.java @@ -16,13 +16,12 @@ package uk.ac.manchester.spinnaker.messages.scp; import static java.lang.String.join; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.nio.charset.StandardCharsets.US_ASCII; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; import static uk.ac.manchester.spinnaker.messages.scp.SCPCommand.CMD_VER; import static uk.ac.manchester.spinnaker.messages.scp.SCPResult.RC_OK; import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_NOT_EXPECTED; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import org.junit.jupiter.api.Test; @@ -65,7 +64,7 @@ void testParseVersionResponseFormat1() byte srcX = 0x7; byte srcY = 0x0; - var data = allocate(41).order(LITTLE_ENDIAN).putShort(PADDING); + var data = alloc(41).putShort(PADDING); data.put(flags).put(tag).put(destPortCPU).put(srcPortCPU); data.put(destY).put(destX).put(srcY).put(srcX); data.putShort(rc).putShort(seq).putShort(p2pAddr); @@ -106,7 +105,7 @@ void testParseVersionResponseFormat2() byte srcX = 0x7; byte srcY = 0x0; - var data = allocate(60).order(LITTLE_ENDIAN).putShort(PADDING); + var data = alloc(60).putShort(PADDING); data.put(flags).put(tag).put(destPortCpu).put(srcPortCpu); data.put(destY).put(destX).put(srcY).put(srcX); data.putShort(rc).putShort(seq).putShort(p2pAddr); diff --git a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TransceiverITCase.java b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TransceiverITCase.java index 3be4b1d9df..6ed52e52ee 100644 --- a/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TransceiverITCase.java +++ b/SpiNNaker-comms/src/test/java/uk/ac/manchester/spinnaker/transceiver/TransceiverITCase.java @@ -18,8 +18,6 @@ import static java.lang.Math.random; import static java.lang.Thread.sleep; import static java.net.InetAddress.getLocalHost; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static java.util.Collections.sort; import static java.util.stream.Collectors.toSet; import static java.util.stream.IntStream.range; @@ -43,6 +41,7 @@ import static uk.ac.manchester.spinnaker.messages.model.RouterDiagnostics.RouterRegister.LOC_PP; import static uk.ac.manchester.spinnaker.messages.model.Signal.STOP; import static uk.ac.manchester.spinnaker.transceiver.CommonMemoryLocations.BUFFERED_SDRAM_START; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.io.File; import java.util.ArrayList; @@ -200,7 +199,7 @@ private void retrieveDetails(Transceiver txrx) throws Exception { } private void readWrite(Transceiver txrx) throws Exception { - var writeData = allocate(1000); + var writeData = alloc(1000); while (writeData.hasRemaining()) { writeData.put((byte) (random() * 256)); } @@ -398,7 +397,7 @@ public void testTransceiver() throws Exception { */ long longVal = 123456789123456789L; int intVal = 123456789; - var longData = allocate(8).order(LITTLE_ENDIAN); + var longData = alloc(8); longData.putLong(longVal).flip(); section("Test reading/writing blobs", () -> { diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/ClearMessage.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/ClearMessage.java index 2f154e14f7..eddd5da191 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/ClearMessage.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/ClearMessage.java @@ -15,11 +15,10 @@ */ package uk.ac.manchester.spinnaker.front_end.download; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.front_end.download.GatherProtocolMessage.ID.CLEAR_TRANSMISSIONS; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_DATA_SPEED_UP; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.nio.ByteBuffer; @@ -45,7 +44,7 @@ public final class ClearMessage extends GatherProtocolMessage { * @return The created message. */ static ClearMessage create(HasCoreLocation destination, int transactionId) { - var payload = allocate(NUM_WORDS * WORD_SIZE).order(LITTLE_ENDIAN); + var payload = alloc(NUM_WORDS * WORD_SIZE); payload.putInt(CLEAR_TRANSMISSIONS.value); payload.putInt(transactionId); payload.flip(); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/MissingSequenceNumbersMessage.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/MissingSequenceNumbersMessage.java index 26585338c5..af7b069d90 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/MissingSequenceNumbersMessage.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/MissingSequenceNumbersMessage.java @@ -16,14 +16,13 @@ package uk.ac.manchester.spinnaker.front_end.download; import static java.lang.Math.min; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.front_end.Constants.NEXT_MESSAGES_COUNT; import static uk.ac.manchester.spinnaker.front_end.download.GatherProtocolMessage.ID.NEXT_MISSING_SEQS; import static uk.ac.manchester.spinnaker.front_end.download.GatherProtocolMessage.ID.START_MISSING_SEQS; import static uk.ac.manchester.spinnaker.messages.Constants.SDP_PAYLOAD_WORDS; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_DATA_SPEED_UP; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.nio.ByteBuffer; @@ -87,7 +86,7 @@ private static int computeNumberOfPackets(int numSequenceNumbers) { */ private static ByteBuffer allocateWords(int numDataWords, int overhead) { int numWords = min(SDP_PAYLOAD_WORDS, numDataWords + overhead); - return allocate(numWords * WORD_SIZE).order(LITTLE_ENDIAN); + return alloc(numWords * WORD_SIZE); } /** diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java index 5b071a45f6..a3668925c1 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/download/StartSendingMessage.java @@ -15,11 +15,10 @@ */ package uk.ac.manchester.spinnaker.front_end.download; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.front_end.download.GatherProtocolMessage.ID.START_SENDING_DATA; import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.EXTRA_MONITOR_CORE_DATA_SPEED_UP; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import java.nio.ByteBuffer; @@ -48,7 +47,7 @@ public final class StartSendingMessage extends GatherProtocolMessage { */ static StartSendingMessage create(HasCoreLocation destination, MemoryLocation address, int length, int transactionId) { - var payload = allocate(NUM_WORDS * WORD_SIZE).order(LITTLE_ENDIAN); + var payload = alloc(NUM_WORDS * WORD_SIZE); payload.putInt(START_SENDING_DATA.value); payload.putInt(transactionId); payload.putInt(address.address()); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java index 0d0c3df556..dda8ac748a 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/BoardWorker.java @@ -15,16 +15,16 @@ */ package uk.ac.manchester.spinnaker.front_end.dse; -import uk.ac.manchester.spinnaker.machine.CoreLocation; +import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.front_end.Constants.CORE_DATA_SDRAM_BASE_TAG; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; +import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.io.IOException; import java.nio.ByteBuffer; - -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import java.util.LinkedHashMap; +import uk.ac.manchester.spinnaker.machine.CoreLocation; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.machine.MemoryLocation; import uk.ac.manchester.spinnaker.messages.model.AppID; @@ -33,7 +33,6 @@ import uk.ac.manchester.spinnaker.storage.StorageException; import uk.ac.manchester.spinnaker.transceiver.ProcessException; import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface; -import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; abstract class BoardWorker { /** The transceiver for talking to the SpiNNaker machine. */ @@ -159,8 +158,7 @@ protected void mallocCore(CoreLocation xyp) throws */ protected void loadCore(CoreLocation xyp) throws IOException, ProcessException, StorageException, InterruptedException { - var pointerTable = - allocate(APP_PTR_TABLE_BYTE_SIZE).order(LITTLE_ENDIAN); + var pointerTable = alloc(APP_PTR_TABLE_BYTE_SIZE); //header pointerTable.putInt(APPDATA_MAGIC_NUM); pointerTable.putInt(DSE_VERSION); diff --git a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java index a6573f2f67..3435fc6300 100644 --- a/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java +++ b/SpiNNaker-front-end/src/main/java/uk/ac/manchester/spinnaker/front_end/dse/FastDataInProtocol.java @@ -18,8 +18,6 @@ import static java.lang.Integer.toUnsignedLong; import static java.lang.Math.min; import static java.lang.String.format; -import static java.nio.ByteBuffer.allocate; -import static java.nio.ByteOrder.LITTLE_ENDIAN; import static uk.ac.manchester.spinnaker.front_end.dse.FastDataInCommandID.SEND_DATA_TO_LOCATION; import static uk.ac.manchester.spinnaker.front_end.dse.FastDataInCommandID.SEND_SEQ_DATA; import static uk.ac.manchester.spinnaker.front_end.dse.FastDataInCommandID.SEND_TELL_DATA_IN; @@ -27,6 +25,7 @@ import static uk.ac.manchester.spinnaker.messages.Constants.WORD_SIZE; import static uk.ac.manchester.spinnaker.messages.sdp.SDPHeader.Flag.REPLY_NOT_EXPECTED; import static uk.ac.manchester.spinnaker.messages.sdp.SDPPort.GATHERER_DATA_SPEED_UP; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.alloc; import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv; import java.nio.ByteBuffer; @@ -121,7 +120,7 @@ private SDPHeader header() { */ SDPMessage dataToLocation(MemoryLocation baseAddress, int numPackets, int transactionId) { - var payload = allocate(BYTES_FOR_LOCATION_PACKET).order(LITTLE_ENDIAN); + var payload = alloc(BYTES_FOR_LOCATION_PACKET); payload.putInt(SEND_DATA_TO_LOCATION.value); payload.putInt(transactionId); payload.putInt(baseAddress.address()); @@ -145,7 +144,7 @@ SDPMessage dataToLocation(MemoryLocation baseAddress, int numPackets, * If the sequence number is nonsense. */ SDPMessage seqData(ByteBuffer data, int seqNum, int transactionId) { - var payload = allocate(BYTES_PER_FULL_PACKET).order(LITTLE_ENDIAN); + var payload = alloc(BYTES_PER_FULL_PACKET); int position = calculatePositionFromSequenceNumber(seqNum); if (position >= data.limit()) { throw new RuntimeException(format( @@ -181,7 +180,7 @@ private int calculatePositionFromSequenceNumber(int seqNum) { * @return The message indicating the end of the data. */ SDPMessage tellDataIn(int transactionId) { - var payload = allocate(BYTES_FOR_TELL_PACKET).order(LITTLE_ENDIAN); + var payload = alloc(BYTES_FOR_TELL_PACKET); payload.putInt(SEND_TELL_DATA_IN.value); payload.putInt(transactionId); payload.flip(); diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java index 2224a9eb64..ce9281608f 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/sqlite/SQLiteDataSpecStorage.java @@ -25,6 +25,7 @@ import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.LIST_ETHERNETS; import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_REGION_POINTER; import static uk.ac.manchester.spinnaker.storage.sqlite.SQL.SET_START_ADDRESS; +import static uk.ac.manchester.spinnaker.utils.ByteBufferUtils.readOnly; import java.nio.ByteBuffer; import java.sql.Connection; @@ -161,7 +162,7 @@ private static HashMap getRegionPointersAndContent( private static ByteBuffer wrapIfNotNull(byte[] buffer) { if (nonNull(buffer)) { - return wrap(buffer).asReadOnlyBuffer(); + return readOnly(wrap(buffer)); } return null; } diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java index 3e19379ff0..47f89603b5 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java @@ -28,23 +28,32 @@ public abstract class ByteBufferUtils { private ByteBufferUtils() { } + private static final int WORD_SIZE = 4; + /** - * Make a slice of a byte buffer without modifying the original buffer. + * Allocate a new little-endian byte buffer. * - * @param src - * The originating buffer. - * @param from - * The offset into the originating buffer where the slice starts. - * @param len - * The length of the slice. - * @return The little-endian slice. This will be read-only if and only if - * the original buffer is read-only. - * @deprecated Replace with - * {@code src.slice(from, len).order(LITTLE_ENDIAN)} + * @param capacity + * The capacity of the buffer. + * @return The buffer. */ - @Deprecated(forRemoval = true) - public static ByteBuffer slice(ByteBuffer src, int from, int len) { - return src.slice(from, len).order(LITTLE_ENDIAN); + public static ByteBuffer alloc(int capacity) { + return ByteBuffer.allocate(capacity).order(LITTLE_ENDIAN); + } + + /** + * 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 = alloc(WORD_SIZE); + b.putInt(value).flip(); + return b; } /** @@ -125,4 +134,15 @@ public static ByteBuffer read(InputStream data, ByteBuffer workingBuffer, } return tmp.limit(size); } + + /** + * Convert the remaining bytes in a buffer into a read-only buffer. + * + * @param buffer + * message buffer to convert + * @return The read-only view. + */ + public static ByteBuffer readOnly(ByteBuffer buffer) { + return buffer.asReadOnlyBuffer().order(LITTLE_ENDIAN); + } } diff --git a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java index dd717bb307..994100bb58 100644 --- a/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java +++ b/SpiNNaker-utils/src/test/java/uk/ac/manchester/spinnaker/utils/TestByteBufferUtils.java @@ -15,12 +15,11 @@ */ package uk.ac.manchester.spinnaker.utils; +import static java.nio.ByteOrder.LITTLE_ENDIAN; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.nio.ReadOnlyBufferException; import org.junit.jupiter.api.Test; @@ -31,10 +30,9 @@ */ public class TestByteBufferUtils { @Test - @SuppressWarnings("removal") public void testSlice() { - var bb = ByteBuffer.allocate(12).order(ByteOrder.LITTLE_ENDIAN); - var s = ByteBufferUtils.slice(bb, 4, 4); + var bb = ByteBufferUtils.alloc(12); + var s = bb.slice(4, 4).order(LITTLE_ENDIAN); s.putInt(0x01020304); // Check range enforcement @@ -46,13 +44,13 @@ public void testSlice() { assertEquals(0, bb.getInt()); // Check read-only carried around - bb = bb.asReadOnlyBuffer(); - var r = ByteBufferUtils.slice(bb, 4, 4); + bb = ByteBufferUtils.readOnly(bb); + var r = bb.slice(4, 4).order(LITTLE_ENDIAN); assertThrows(ReadOnlyBufferException.class, () -> r.putInt(0x5060708)); assertEquals(0x01020304, r.getInt()); // Check range sanity enforced assertThrows(IndexOutOfBoundsException.class, - () -> ByteBufferUtils.slice(r, 0, 16)); + () -> r.slice(0, 16)); } } From f71b53c53393fba541b92d2139342754212c7c81 Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 21 Jun 2023 14:36:16 +0100 Subject: [PATCH 105/194] Ran into https://bugs.eclipse.org/bugs/show_bug.cgi?id=576378 --- .../uk/ac/manchester/spinnaker/messages/bmp/BMPRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f61217ab91..968b197666 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 @@ -202,7 +202,7 @@ public String toString() { */ @UsedInJavadocOnly(CheckOKResponse.class) public static sealed class BMPResponse extends SCPResponse - permits PayloadedResponse { + permits PayloadedResponse { /** * Make a response object. * From d1f9e88fc4c523566fde8387ba7c614b5899964d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:05:08 +0000 Subject: [PATCH 106/194] Bump hibernate-validator from 8.0.0.Final to 8.0.1.Final Bumps [hibernate-validator](https://github.com/hibernate/hibernate-validator) from 8.0.0.Final to 8.0.1.Final. - [Changelog](https://github.com/hibernate/hibernate-validator/blob/main/changelog.txt) - [Commits](https://github.com/hibernate/hibernate-validator/compare/8.0.0.Final...8.0.1.Final) --- updated-dependencies: - dependency-name: org.hibernate.validator:hibernate-validator dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1440cc9287..ee550ac78c 100644 --- a/pom.xml +++ b/pom.xml @@ -369,7 +369,7 @@ limitations under the License. org.hibernate.validator hibernate-validator - 8.0.0.Final + 8.0.1.Final From 8edf1cbf3ecf429598bf60ffd647c9af9056d4a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:05:32 +0000 Subject: [PATCH 107/194] Bump spring.boot.version from 3.1.0 to 3.1.1 Bumps `spring.boot.version` from 3.1.0 to 3.1.1. Updates `spring-boot-maven-plugin` from 3.1.0 to 3.1.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.0...v3.1.1) Updates `spring-boot-dependencies` from 3.1.0 to 3.1.1 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.0...v3.1.1) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1440cc9287..eb6ea761b2 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ limitations under the License. 2.20.0 6.0.10 - 3.1.0 + 3.1.1 - 6.1.1 + 6.1.2 4.0.2 2.15.2 From b051c5aed4d9e183acdb243c2f42bacdfcb13342 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:36:35 +0000 Subject: [PATCH 112/194] Bump swagger-ui from 5.1.0 to 5.1.2 Bumps [swagger-ui](https://github.com/webjars/swagger-ui) from 5.1.0 to 5.1.2. - [Commits](https://github.com/webjars/swagger-ui/compare/swagger-ui-5.1.0...swagger-ui-5.1.2) --- updated-dependencies: - dependency-name: org.webjars:swagger-ui dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 58bd942404..27f2eb9cc8 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ limitations under the License. 2.14 3.42.0.0 22.0.0 - 5.1.0 + 5.1.2 1.0.5 2.7.3 2.20.0 From 7b1f02734617a2a462cf61773d1b698a116518eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:26:18 +0000 Subject: [PATCH 113/194] Bump spring.boot.version from 3.1.1 to 3.1.2 Bumps `spring.boot.version` from 3.1.1 to 3.1.2. Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.1.1 to 3.1.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.1...v3.1.2) Updates `org.springframework.boot:spring-boot-dependencies` from 3.1.1 to 3.1.2 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.1...v3.1.2) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dd76602c89..ab40fcd659 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.20.0 6.0.11 - 3.1.1 + 3.1.2 - 6.1.2 + 6.1.3 4.0.2 2.15.2 From ef446905b7862959dbf499ec2767477901264e0a Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Wed, 23 Aug 2023 17:13:58 +0100 Subject: [PATCH 164/194] Use the Serial annotation --- .../alloc/admin/AdminControllerImpl.java | 5 +++++ .../alloc/admin/MachineDefinitionLoader.java | 2 ++ .../alloc/admin/MachineStateControl.java | 2 ++ .../spinnaker/alloc/allocator/Spalloc.java | 5 +++++ .../spinnaker/alloc/bmp/FirmwareLoader.java | 5 +++++ .../alloc/bmp/TransceiverFactory.java | 2 ++ .../alloc/security/LocalAuthProviderImpl.java | 6 ++++++ .../spinnaker/alloc/security/Permit.java | 2 ++ .../alloc/security/SimpleGrantedAuthority.java | 3 +++ .../alloc/web/RequestFailedException.java | 7 +++++++ .../spinnaker/alloc/client/SpallocClient.java | 2 ++ .../spinnaker/messages/model/ADCInfo.java | 2 ++ .../spinnaker/messages/model/Blacklist.java | 4 ++++ .../model/MemoryAllocationFailedException.java | 3 +++ .../model/UnexpectedResponseCodeException.java | 3 +++ .../model/UnroutableMessageException.java | 3 +++ .../exceptions/JobDestroyedException.java | 3 +++ .../exceptions/SpallocProtocolException.java | 2 ++ .../SpallocProtocolTimeoutException.java | 2 ++ .../exceptions/SpallocServerException.java | 3 +++ .../SpallocStateChangeTimeoutException.java | 3 +++ .../transceiver/BMPSendFailedException.java | 2 ++ .../transceiver/BMPSendTimedOutException.java | 2 ++ .../transceiver/CoresNotInStateException.java | 2 ++ .../transceiver/ProcessException.java | 18 ++++++++++++++++++ .../transceiver/SpinnmanException.java | 3 +++ .../spinnaker/transceiver/TxrxProcess.java | 4 ++++ .../nmpi/model/machine/SpinnakerMachine.java | 2 ++ .../spinnaker/storage/StorageException.java | 3 +++ .../manchester/spinnaker/utils/DefaultMap.java | 2 ++ .../spinnaker/utils/InetFactory.java | 2 ++ 31 files changed, 109 insertions(+) diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java index a2c1f0b4d4..c7483bed56 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/AdminControllerImpl.java @@ -85,6 +85,7 @@ import static uk.ac.manchester.spinnaker.alloc.web.SystemController.USER_MAY_CHANGE_PASSWORD; import java.io.IOException; +import java.io.Serial; import java.net.URI; import java.security.Principal; import java.util.HashMap; @@ -331,6 +332,7 @@ ModelAndView dbException(DataAccessException e, HandlerMethod hm) { } private static class AdminException extends RuntimeException { + @Serial private static final long serialVersionUID = 8401068773689159840L; AdminException(String message) { @@ -339,6 +341,7 @@ private static class AdminException extends RuntimeException { } private static final class NoUser extends AdminException { + @Serial private static final long serialVersionUID = 6430674580385445089L; private NoUser() { @@ -347,6 +350,7 @@ private NoUser() { } private static final class NoGroup extends AdminException { + @Serial private static final long serialVersionUID = -4593707687103047377L; private NoGroup() { @@ -355,6 +359,7 @@ private NoGroup() { } private static final class NoBoard extends AdminException { + @Serial private static final long serialVersionUID = -4017368969526085002L; private NoBoard() { diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java index 0e093dfd10..ecad0a2ce0 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineDefinitionLoader.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.Serial; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -627,6 +628,7 @@ public void loadMachineDefinition(Machine machine) { * @author Donal Fellows */ public static class InsertFailedException extends RuntimeException { + @Serial private static final long serialVersionUID = -4930512416142843777L; InsertFailedException(String table) { diff --git a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java index 98ab9371a3..2d51fb0366 100644 --- a/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java +++ b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/admin/MachineStateControl.java @@ -28,6 +28,7 @@ import static uk.ac.manchester.spinnaker.utils.CollectionUtils.batch; import static uk.ac.manchester.spinnaker.utils.CollectionUtils.lmap; +import java.io.Serial; import java.time.Instant; import java.util.HashSet; import java.util.List; @@ -463,6 +464,7 @@ public void setMachineState(@NotBlank String machineName, * @author Donal Fellows */ public static final class MachineStateException extends RuntimeException { + @Serial private static final long serialVersionUID = -6450838951059318431L; private MachineStateException(String msg, Exception exn) { 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 a944d4d810..ecb4986a44 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 @@ -36,6 +36,7 @@ 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; @@ -1880,6 +1881,7 @@ public Job getJob() { } static class PartialJobException extends IllegalStateException { + @Serial private static final long serialVersionUID = 2997856394666135483L; PartialJobException() { @@ -1903,6 +1905,7 @@ class ReportRollbackExn extends RuntimeException { } abstract class GroupsException extends RuntimeException { + @Serial private static final long serialVersionUID = 6607077117924279611L; GroupsException(String message) { @@ -1915,6 +1918,7 @@ abstract class GroupsException extends RuntimeException { } class NoSuchGroupException extends GroupsException { + @Serial private static final long serialVersionUID = 5193818294198205503L; @FormatMethod @@ -1924,6 +1928,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/bmp/FirmwareLoader.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/bmp/FirmwareLoader.java index 015732c184..8f8edbadae 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 @@ -42,6 +42,7 @@ 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; @@ -169,6 +170,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) { @@ -178,6 +180,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. */ @@ -191,6 +194,7 @@ public static class UpdateFailedException extends FirmwareLoaderException { /** 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 +208,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) { 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 d215bb3952..fd09ec0c0e 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 @@ -21,6 +21,7 @@ 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; @@ -119,6 +120,7 @@ public BMPTransceiverInterface getTransciever(Machine machineDescription, } private static class TransceiverFactoryException extends RuntimeException { + @Serial private static final long serialVersionUID = 2102592240724419836L; TransceiverFactoryException(String msg, Exception e) { 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 0559066209..bd243e4f5b 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; @@ -190,6 +191,7 @@ private void initUserIfNecessary() { } private static final class SetupException extends RuntimeException { + @Serial private static final long serialVersionUID = -3915472090182223715L; SetupException(String message) { @@ -337,6 +339,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, @@ -447,6 +450,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; @@ -703,6 +707,7 @@ void apply(int userId) { @Immutable static final class CollabratoryAuthority extends SimpleGrantedAuthority { + @Serial private static final long serialVersionUID = 4964366746649162092L; private final String collabratory; @@ -719,6 +724,7 @@ String getCollabratory() { @Immutable static final class OrganisationAuthority extends SimpleGrantedAuthority { + @Serial private static final long serialVersionUID = 8260068770503054502L; private final String organisation; 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..2f1722831d 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; @@ -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/SimpleGrantedAuthority.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/security/SimpleGrantedAuthority.java index 20d10c565a..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,6 +15,8 @@ */ package uk.ac.manchester.spinnaker.alloc.security; +import java.io.Serial; + import org.springframework.security.core.GrantedAuthority; import com.google.errorprone.annotations.Immutable; @@ -28,6 +30,7 @@ @Immutable 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/web/RequestFailedException.java b/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/web/RequestFailedException.java index 8c4da587cd..cabe3a64f0 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 @@ -27,6 +27,8 @@ import static javax.ws.rs.core.Response.Status.Family.SERVER_ERROR; import static org.slf4j.LoggerFactory.getLogger; +import java.io.Serial; + import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -43,6 +45,7 @@ * @author Donal Fellows */ public class RequestFailedException extends RuntimeException { + @Serial private static final long serialVersionUID = -7522760691720854101L; /** The status code. */ @@ -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-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..a890f7dcfe 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,6 +22,7 @@ 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; @@ -387,6 +388,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/messages/model/ADCInfo.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ADCInfo.java index f469e7a1fc..d238f56a4c 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ADCInfo.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/ADCInfo.java @@ -22,12 +22,14 @@ import static uk.ac.manchester.spinnaker.messages.Constants.BMP_V_SCALE_2_5; import static uk.ac.manchester.spinnaker.messages.Constants.BMP_V_SCALE_3_3; +import java.io.Serial; import java.io.Serializable; import java.nio.ByteBuffer; /** Container for the board status data thats been retrieved from a BMP. */ @SARKStruct(value = "board_stat_t", api = SARKStruct.API.BMP) public final class ADCInfo implements Serializable { + @Serial private static final long serialVersionUID = 8245655123474028462L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java index 11885c4b69..c275be7ea0 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/Blacklist.java @@ -47,6 +47,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serial; import java.io.Serializable; import java.nio.Buffer; import java.nio.ByteBuffer; @@ -82,6 +83,7 @@ * @author Donal Fellows */ public final class Blacklist implements Serializable { + @Serial private static final long serialVersionUID = -7759940789892168209L; private static final Logger log = getLogger(Blacklist.class); @@ -518,6 +520,7 @@ public String toString() { * If output fails. * @see ObjectOutputStream#defaultWriteObject() */ + @Serial private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeInt(rawData.remaining()); @@ -542,6 +545,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { * if the class of a serialized object could not be found. * @see ObjectInputStream#defaultReadObject() */ + @Serial private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/MemoryAllocationFailedException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/MemoryAllocationFailedException.java index 3d2377a598..e08ba2ce3b 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/MemoryAllocationFailedException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/MemoryAllocationFailedException.java @@ -15,10 +15,13 @@ */ package uk.ac.manchester.spinnaker.messages.model; +import java.io.Serial; + /** * Indicate that a memory allocation operation has failed. */ public class MemoryAllocationFailedException extends Exception { + @Serial private static final long serialVersionUID = 4463116302552127934L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnexpectedResponseCodeException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnexpectedResponseCodeException.java index 10771e9210..c5d8542087 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnexpectedResponseCodeException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnexpectedResponseCodeException.java @@ -17,6 +17,8 @@ import static java.lang.String.format; +import java.io.Serial; + import uk.ac.manchester.spinnaker.messages.scp.SCPResult; /** @@ -24,6 +26,7 @@ * current operation. */ public class UnexpectedResponseCodeException extends Exception { + @Serial private static final long serialVersionUID = 7864690081287752744L; /** The response that cause this exception to be thrown, if known. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java index f4e540bc7f..a17adca075 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/messages/model/UnroutableMessageException.java @@ -15,6 +15,8 @@ */ package uk.ac.manchester.spinnaker.messages.model; +import java.io.Serial; + import uk.ac.manchester.spinnaker.messages.scp.SCPResult; import uk.ac.manchester.spinnaker.messages.sdp.SDPHeader; @@ -24,6 +26,7 @@ */ public class UnroutableMessageException extends UnexpectedResponseCodeException { + @Serial private static final long serialVersionUID = 2106128799950032057L; /** The full header from the response message. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/JobDestroyedException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/JobDestroyedException.java index f1e827d5e2..6a76bc1f74 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/JobDestroyedException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/JobDestroyedException.java @@ -15,8 +15,11 @@ */ package uk.ac.manchester.spinnaker.spalloc.exceptions; +import java.io.Serial; + /** Thrown when the job was destroyed while waiting for it to become ready. */ public class JobDestroyedException extends Exception { + @Serial private static final long serialVersionUID = 6082560756316191208L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolException.java index 9a62b7e3be..ffff533182 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolException.java @@ -16,9 +16,11 @@ package uk.ac.manchester.spinnaker.spalloc.exceptions; import java.io.IOException; +import java.io.Serial; /** Thrown when a network-level problem occurs during protocol handling. */ public class SpallocProtocolException extends IOException { + @Serial private static final long serialVersionUID = -1591596793445886688L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolTimeoutException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolTimeoutException.java index 57229de5a6..c3fba9822a 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolTimeoutException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocProtocolTimeoutException.java @@ -16,9 +16,11 @@ package uk.ac.manchester.spinnaker.spalloc.exceptions; import java.io.IOException; +import java.io.Serial; /** Thrown upon a protocol-level timeout. */ public class SpallocProtocolTimeoutException extends IOException { + @Serial private static final long serialVersionUID = -3573271239107837119L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocServerException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocServerException.java index fa42468ae8..e6626e7600 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocServerException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocServerException.java @@ -15,6 +15,8 @@ */ package uk.ac.manchester.spinnaker.spalloc.exceptions; +import java.io.Serial; + import uk.ac.manchester.spinnaker.spalloc.messages.ExceptionResponse; /** @@ -22,6 +24,7 @@ * a message. */ public class SpallocServerException extends Exception { + @Serial private static final long serialVersionUID = 3865188016221866202L; /** diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocStateChangeTimeoutException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocStateChangeTimeoutException.java index bb1c480051..61485edfda 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocStateChangeTimeoutException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/spalloc/exceptions/SpallocStateChangeTimeoutException.java @@ -15,8 +15,11 @@ */ package uk.ac.manchester.spinnaker.spalloc.exceptions; +import java.io.Serial; + /** Thrown when a state change takes too long to occur. */ public class SpallocStateChangeTimeoutException extends Exception { + @Serial private static final long serialVersionUID = 4879238794331037892L; /** Create an instance. */ diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendFailedException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendFailedException.java index 2705fd7e91..4c1cbace5e 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendFailedException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendFailedException.java @@ -19,6 +19,7 @@ import static uk.ac.manchester.spinnaker.transceiver.BMPCommandProcess.BMP_RETRIES; import java.io.IOException; +import java.io.Serial; import java.util.List; import uk.ac.manchester.spinnaker.machine.HasCoreLocation; @@ -28,6 +29,7 @@ * Indicates that message sending to a BMP failed for various reasons. */ public final class BMPSendFailedException extends IOException { + @Serial private static final long serialVersionUID = -7806549580351626377L; BMPSendFailedException(SCPRequest req, HasCoreLocation core, diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendTimedOutException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendTimedOutException.java index 5183636bc9..985d0311bd 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendTimedOutException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/BMPSendTimedOutException.java @@ -18,6 +18,7 @@ import static java.lang.String.format; import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC; +import java.io.Serial; import java.net.SocketTimeoutException; import uk.ac.manchester.spinnaker.messages.scp.SCPRequest; @@ -27,6 +28,7 @@ */ public final class BMPSendTimedOutException extends SocketTimeoutException { + @Serial private static final long serialVersionUID = 1660563278795501381L; BMPSendTimedOutException(SCPRequest req, int timeout) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CoresNotInStateException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CoresNotInStateException.java index 7162b52340..140da9b4a5 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CoresNotInStateException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/CoresNotInStateException.java @@ -19,6 +19,7 @@ import static java.lang.String.format; import static uk.ac.manchester.spinnaker.utils.UnitConstants.MSEC_PER_SEC; +import java.io.Serial; import java.util.EnumSet; import uk.ac.manchester.spinnaker.machine.CoreSubsets; @@ -30,6 +31,7 @@ * @author Donal Fellows */ public class CoresNotInStateException extends SpinnmanException { + @Serial private static final long serialVersionUID = 1790369744408178478L; private static final String OP_TMPL = diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java index 5d88c7715e..590332e118 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/ProcessException.java @@ -18,6 +18,8 @@ import static java.lang.String.format; import static java.util.Objects.requireNonNull; +import java.io.Serial; + import uk.ac.manchester.spinnaker.machine.HasCoreLocation; import uk.ac.manchester.spinnaker.messages.model.UnexpectedResponseCodeException; import uk.ac.manchester.spinnaker.messages.scp.SCPResult; @@ -26,6 +28,7 @@ * Encapsulates exceptions from processes which communicate with some core/chip. */ public class ProcessException extends SpinnmanException { + @Serial private static final long serialVersionUID = 5198868033333540659L; private static final String S = " "; // five spaces @@ -164,6 +167,7 @@ private PermanentProcessException(HasCoreLocation core, * message, indicating that the packet length was wrong. */ public static final class BadPacketLength extends CallerProcessException { + @Serial private static final long serialVersionUID = 4329836896716525422L; private BadPacketLength(HasCoreLocation core, @@ -177,6 +181,7 @@ private BadPacketLength(HasCoreLocation core, * message, indicating that the checksum was wrong. */ public static final class BadChecksum extends CallerProcessException { + @Serial private static final long serialVersionUID = -5660270018252119601L; private BadChecksum(HasCoreLocation core, @@ -191,6 +196,7 @@ private BadChecksum(HasCoreLocation core, * destination. */ public static final class BadCommand extends CallerProcessException { + @Serial private static final long serialVersionUID = 2446636059917726286L; private BadCommand(HasCoreLocation core, @@ -204,6 +210,7 @@ private BadCommand(HasCoreLocation core, * message, indicating that the arguments to the command are wrong. */ public static final class InvalidArguments extends CallerProcessException { + @Serial private static final long serialVersionUID = 3907517289211998444L; private InvalidArguments(HasCoreLocation core, @@ -217,6 +224,7 @@ private InvalidArguments(HasCoreLocation core, * message, indicating that the SCP port was out of range. */ public static final class BadSCPPort extends CallerProcessException { + @Serial private static final long serialVersionUID = -5171910962257032626L; private BadSCPPort(HasCoreLocation core, @@ -231,6 +239,7 @@ private BadSCPPort(HasCoreLocation core, * timed out. */ public static final class TimedOut extends TransientProcessException { + @Serial private static final long serialVersionUID = -298985937364034661L; private TimedOut(HasCoreLocation core, @@ -245,6 +254,7 @@ private TimedOut(HasCoreLocation core, * for some reason. */ public static final class NoP2PRoute extends PermanentProcessException { + @Serial private static final long serialVersionUID = -6132417061161625508L; private NoP2PRoute(HasCoreLocation core, @@ -258,6 +268,7 @@ private NoP2PRoute(HasCoreLocation core, * message, indicating that the destination core number was out of range. */ public static final class BadCPUNumber extends CallerProcessException { + @Serial private static final long serialVersionUID = 6532417803149087690L; private BadCPUNumber(HasCoreLocation core, @@ -273,6 +284,7 @@ private BadCPUNumber(HasCoreLocation core, */ public static final class DeadDestination extends PermanentProcessException { + @Serial private static final long serialVersionUID = -3842030808096451015L; private DeadDestination(HasCoreLocation core, @@ -287,6 +299,7 @@ private DeadDestination(HasCoreLocation core, */ public static final class NoBufferAvailable extends TransientProcessException { + @Serial private static final long serialVersionUID = 3647501054775981197L; private NoBufferAvailable(HasCoreLocation core, @@ -301,6 +314,7 @@ private NoBufferAvailable(HasCoreLocation core, * messaging failed because the channel open failed. */ public static final class P2PNoReply extends TransientProcessException { + @Serial private static final long serialVersionUID = 2196366740196153289L; private P2PNoReply(HasCoreLocation core, @@ -315,6 +329,7 @@ private P2PNoReply(HasCoreLocation core, * the inter-SCAMP messaging rejected the message. */ public static final class P2PReject extends TransientProcessException { + @Serial private static final long serialVersionUID = -2903670314989693747L; private P2PReject(HasCoreLocation core, @@ -329,6 +344,7 @@ private P2PReject(HasCoreLocation core, * the inter-SCAMP messaging was busy. */ public static final class P2PBusy extends TransientProcessException { + @Serial private static final long serialVersionUID = 4445680981367158468L; private P2PBusy(HasCoreLocation core, @@ -343,6 +359,7 @@ private P2PBusy(HasCoreLocation core, * the inter-SCAMP messaging did not respond. */ public static final class P2PTimedOut extends TransientProcessException { + @Serial private static final long serialVersionUID = -7686611958418374003L; private P2PTimedOut(HasCoreLocation core, @@ -357,6 +374,7 @@ private P2PTimedOut(HasCoreLocation core, */ public static final class PacketTransmissionFailed extends TransientProcessException { + @Serial private static final long serialVersionUID = 5119831821960433468L; private PacketTransmissionFailed(HasCoreLocation core, diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/SpinnmanException.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/SpinnmanException.java index 0c02eade0f..320c63bfcb 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/SpinnmanException.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/SpinnmanException.java @@ -15,10 +15,13 @@ */ package uk.ac.manchester.spinnaker.transceiver; +import java.io.Serial; + /** * Basic exception from the transceiver. */ public class SpinnmanException extends Exception { + @Serial private static final long serialVersionUID = 4307580491294281556L; SpinnmanException(String message) { diff --git a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java index 3122015710..3ee4b8d294 100644 --- a/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java +++ b/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/transceiver/TxrxProcess.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InterruptedIOException; +import java.io.Serial; import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -926,6 +927,7 @@ public String toString() { * Indicates that a request timed out. */ static class SendTimedOutException extends SocketTimeoutException { + @Serial private static final long serialVersionUID = -7911020002602751941L; /** @@ -945,6 +947,7 @@ static class SendTimedOutException extends SocketTimeoutException { * Indicates that a request could not be sent. */ static class SendFailedException extends IOException { + @Serial private static final long serialVersionUID = -5555562816486761027L; /** @@ -969,6 +972,7 @@ static class SendFailedException extends IOException { */ static class DuplicateSequenceNumberException extends IllegalThreadStateException { + @Serial private static final long serialVersionUID = -4033792283948201730L; DuplicateSequenceNumberException() { diff --git a/SpiNNaker-nmpimodel/src/main/java/uk/ac/manchester/spinnaker/nmpi/model/machine/SpinnakerMachine.java b/SpiNNaker-nmpimodel/src/main/java/uk/ac/manchester/spinnaker/nmpi/model/machine/SpinnakerMachine.java index 3d90338985..e7ee540b84 100644 --- a/SpiNNaker-nmpimodel/src/main/java/uk/ac/manchester/spinnaker/nmpi/model/machine/SpinnakerMachine.java +++ b/SpiNNaker-nmpimodel/src/main/java/uk/ac/manchester/spinnaker/nmpi/model/machine/SpinnakerMachine.java @@ -20,6 +20,7 @@ import static java.util.Comparator.nullsFirst; import static java.util.Objects.nonNull; +import java.io.Serial; import java.io.Serializable; import java.util.Arrays; import java.util.Comparator; @@ -31,6 +32,7 @@ public class SpinnakerMachine implements Serializable, Comparable { /** Serial version UID. */ + @Serial private static final long serialVersionUID = -2247744763327978524L; /** The number of parts that make up a machine description as a string. */ diff --git a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/StorageException.java b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/StorageException.java index f366635ecb..fa3748e4d1 100644 --- a/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/StorageException.java +++ b/SpiNNaker-storage/src/main/java/uk/ac/manchester/spinnaker/storage/StorageException.java @@ -15,12 +15,15 @@ */ package uk.ac.manchester.spinnaker.storage; +import java.io.Serial; + /** * Exceptions caused by the storage system. * * @author Donal Fellows */ public class StorageException extends Exception { + @Serial private static final long serialVersionUID = 3553555491656536568L; /** diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/DefaultMap.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/DefaultMap.java index c1bcf90901..d79f7a8c6c 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/DefaultMap.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/DefaultMap.java @@ -17,6 +17,7 @@ import static java.util.Objects.requireNonNull; +import java.io.Serial; import java.util.HashMap; import java.util.function.BiFunction; import java.util.function.Function; @@ -36,6 +37,7 @@ * The type of values. */ public class DefaultMap extends HashMap { + @Serial private static final long serialVersionUID = -3805864660424802906L; /** diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/InetFactory.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/InetFactory.java index bf899b00c9..4776992d9d 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/InetFactory.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/InetFactory.java @@ -15,6 +15,7 @@ */ package uk.ac.manchester.spinnaker.utils; +import java.io.Serial; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -126,6 +127,7 @@ public static Inet4Address getByNameQuietly(String host) { */ public static class Inet6NotSupportedException extends UnknownHostException { + @Serial private static final long serialVersionUID = -7430619278827122304L; /** From 24c1f2196f04b492c6e4e3dd4eef441bfe4df393 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:44:35 +0000 Subject: [PATCH 165/194] Bump com.puppycrawl.tools:checkstyle from 10.12.2 to 10.12.3 Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.12.2 to 10.12.3. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.2...checkstyle-10.12.3) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7a67d9cc9e..63928abecf 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ limitations under the License. 5.10.0 1.10.0 - 10.12.2 + 10.12.3 3.5.0 3.1.2 From ac6a5393fcc92901509575c79af6f9c56045ee32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:44:46 +0000 Subject: [PATCH 166/194] Bump com.puppycrawl.tools:checkstyle from 10.12.2 to 10.12.3 Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.12.2 to 10.12.3. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.2...checkstyle-10.12.3) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be4766c98c..6b0ce284ca 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ limitations under the License. 5.10.0 1.10.0 - 10.12.2 + 10.12.3 3.5.0 3.1.2 From 96c4ecc7b1aefac7c7c35d90e21110a25434fca9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:45:35 +0000 Subject: [PATCH 167/194] Bump spring.boot.version from 3.1.2 to 3.1.3 Bumps `spring.boot.version` from 3.1.2 to 3.1.3. Updates `org.springframework.boot:spring-boot-starter` from 3.1.2 to 3.1.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.2...v3.1.3) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.1.2 to 3.1.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.2...v3.1.3) Updates `org.springframework.boot:spring-boot-dependencies` from 3.1.2 to 3.1.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.2...v3.1.3) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be4766c98c..231e8ad411 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.20.0 6.0.11 - 3.1.2 + 3.1.3 - 5.8.6 + 5.8.7 3.6.2 2.15.2 From bbb825b7bf91a849e3d44abdc6a41c84abe275c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:28:43 +0000 Subject: [PATCH 172/194] Bump cxf.version from 4.0.2 to 4.0.3 Bumps `cxf.version` from 4.0.2 to 4.0.3. Updates `org.apache.cxf:cxf-rt-frontend-jaxrs` from 4.0.2 to 4.0.3 Updates `org.apache.cxf:cxf-spring-boot-starter-jaxrs` from 4.0.2 to 4.0.3 Updates `org.apache.cxf:cxf-rt-rs-client` from 4.0.2 to 4.0.3 Updates `org.apache.cxf:cxf-bom` from 4.0.2 to 4.0.3 --- updated-dependencies: - dependency-name: org.apache.cxf:cxf-rt-frontend-jaxrs dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.cxf:cxf-spring-boot-starter-jaxrs dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.cxf:cxf-rt-rs-client dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.cxf:cxf-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 438c09541a..2a146fcdcb 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ limitations under the License. --> 6.1.3 - 4.0.2 + 4.0.3 2.15.2 2.14 3.43.0.0 From 6d7044880f9949e6b2fa89234df0fc57739dc413 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:29:11 +0000 Subject: [PATCH 173/194] Bump spring.version from 6.0.11 to 6.0.12 Bumps `spring.version` from 6.0.11 to 6.0.12. Updates `org.springframework:spring-framework-bom` from 6.0.11 to 6.0.12 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.11...v6.0.12) Updates `org.springframework:spring-test` from 6.0.11 to 6.0.12 - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.0.11...v6.0.12) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework:spring-test dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 438c09541a..e667b66ae0 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ limitations under the License. 2.0.9 2.20.0 - 6.0.11 + 6.0.12 3.1.3 - 6.1.3 + 6.1.4 4.0.2 2.15.2 From 7507f9b1bbb7935986bb581bab1018c2ece6e92f Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Thu, 21 Sep 2023 16:39:23 +0100 Subject: [PATCH 175/194] Found a spot that could be a var --- .../java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java index f568450314..f5e908e462 100644 --- a/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java +++ b/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/ByteBufferUtils.java @@ -86,9 +86,8 @@ public static ByteBuffer limitSlice(ByteBuffer src, int maxSize) { */ public static MappableIterable sliceUp(ByteBuffer src, int chunkSize) { + var b = src.duplicate(); return () -> new Iterator<>() { - final ByteBuffer b = src.duplicate(); - @Override public boolean hasNext() { return b.hasRemaining(); From c7fb295811302300e1375c3613a414effb02266d Mon Sep 17 00:00:00 2001 From: "Donal K. Fellows" Date: Mon, 25 Sep 2023 09:49:15 +0100 Subject: [PATCH 176/194] Erratum --- .../uk/ac/manchester/spinnaker/alloc/bmp/MockTransceiver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4605a9a7e9..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 @@ -233,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) { From 95602885e1405a1777118db33fbc4382afbe3beb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:49:09 +0000 Subject: [PATCH 177/194] Bump error-prone.version from 2.21.1 to 2.22.0 Bumps `error-prone.version` from 2.21.1 to 2.22.0. Updates `com.google.errorprone:error_prone_annotations` from 2.21.1 to 2.22.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.21.1...v2.22.0) Updates `com.google.errorprone:error_prone_core` from 2.21.1 to 2.22.0 - [Release notes](https://github.com/google/error-prone/releases) - [Commits](https://github.com/google/error-prone/compare/v2.21.1...v2.22.0) --- updated-dependencies: - dependency-name: com.google.errorprone:error_prone_annotations dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.errorprone:error_prone_core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74547b8074..48f04d6477 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ limitations under the License. 5.7.2 1.0.5 2.7.3 - 2.21.1 + 2.22.0 4.7.5 8.1.0 1.19.0 From 23a0aa85c4beded6e816d590406017c789db24d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:49:38 +0000 Subject: [PATCH 178/194] Bump spring.boot.version from 3.1.3 to 3.1.4 Bumps `spring.boot.version` from 3.1.3 to 3.1.4. Updates `org.springframework.boot:spring-boot-starter` from 3.1.3 to 3.1.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.3...v3.1.4) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.1.3 to 3.1.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.3...v3.1.4) Updates `org.springframework.boot:spring-boot-dependencies` from 3.1.3 to 3.1.4 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.3...v3.1.4) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74547b8074..d514020598 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.20.0 6.0.12 - 3.1.3 + 3.1.4 From 5b79610ecab3957dfcdf95146fb836cd970132ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:44:29 +0000 Subject: [PATCH 192/194] Bump spring.boot.version from 3.1.4 to 3.3.3 Bumps `spring.boot.version` from 3.1.4 to 3.3.3. Updates `org.springframework.boot:spring-boot-starter` from 3.1.4 to 3.3.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.4...v3.3.3) Updates `org.springframework.boot:spring-boot-maven-plugin` from 3.1.4 to 3.3.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.4...v3.3.3) Updates `org.springframework.boot:spring-boot-dependencies` from 3.1.4 to 3.3.3 - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.1.4...v3.3.3) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.springframework.boot:spring-boot-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.springframework.boot:spring-boot-dependencies dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a03d377c23..344259de8b 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ limitations under the License. 2.23.1 6.0.12 - 3.1.4 + 3.3.3