• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / JavaSpiNNaker / 13333362741

14 Feb 2025 04:31PM UTC coverage: 38.411% (-0.2%) from 38.564%
13333362741

push

github

rowleya
Put this in the right place and fill in the gaps

12 of 374 new or added lines in 3 files covered. (3.21%)

227 existing lines in 8 files now uncovered.

9168 of 23868 relevant lines covered (38.41%)

1.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/SpiNNaker-comms/src/main/java/uk/ac/manchester/spinnaker/alloc/client/SpallocClient.java
1
/*
2
 * Copyright (c) 2021 The University of Manchester
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package uk.ac.manchester.spinnaker.alloc.client;
17

18
import static java.lang.String.join;
19
import static java.nio.charset.StandardCharsets.UTF_8;
20
import static org.apache.commons.io.IOUtils.readLines;
21

22
import java.io.FileNotFoundException;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.nio.ByteBuffer;
26
import java.util.List;
27
import java.util.stream.Stream;
28

29
import javax.validation.Valid;
30
import javax.validation.constraints.NotNull;
31

32
import com.google.errorprone.annotations.MustBeClosed;
33

34
import uk.ac.manchester.spinnaker.machine.HasChipLocation;
35
import uk.ac.manchester.spinnaker.machine.MemoryLocation;
36
import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords;
37
import uk.ac.manchester.spinnaker.machine.board.TriadCoords;
38
import uk.ac.manchester.spinnaker.messages.model.Version;
39
import uk.ac.manchester.spinnaker.spalloc.exceptions.SpallocServerException;
40
import uk.ac.manchester.spinnaker.transceiver.SpinnmanException;
41
import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface;
42
import uk.ac.manchester.spinnaker.utils.validation.IPAddress;
43

44
/**
45
 * An API for talking to the Spalloc service.
46
 *
47
 * @see SpallocClientFactory
48
 * @author Donal Fellows
49
 */
50
public interface SpallocClient {
51
        /**
52
         * Get the server version ID.
53
         *
54
         * @return A version ID.
55
         * @throws IOException
56
         *             If things go wrong.
57
         */
58
        Version getVersion() throws IOException;
59

60
        /**
61
         * Get a list of all Spalloc machines.
62
         *
63
         * @return The list of machines.
64
         * @throws IOException
65
         *             If things go wrong.
66
         */
67
        List<Machine> listMachines() throws IOException;
68

69
        /**
70
         * List the existing non-terminated jobs.
71
         *
72
         * @param waitForChange
73
         *            If {@code true}, will wait until the list of jobs may have
74
         *            changed. (Best-effort only; waiting time is bounded at 30
75
         *            seconds.)
76
         * @return A list of jobs.
77
         * @throws IOException
78
         *             If things go wrong.
79
         */
80
        List<Job> listJobs(boolean waitForChange) throws IOException;
81

82
        /**
83
         * List the jobs, including the deleted ones.
84
         * <p>
85
         * <strong>NB:</strong> Care should be taken; this may produce a lot of
86
         * output.
87
         *
88
         * @param waitForChange
89
         *            If {@code true}, will wait until the list of jobs may have
90
         *            changed. (Best-effort only; waiting time is bounded at 30
91
         *            seconds.)
92
         * @return A stream of jobs.
93
         * @throws IOException
94
         *             If things go wrong.
95
         */
96
        Stream<Job> listJobsWithDeleted(boolean waitForChange) throws IOException;
97

98
        /**
99
         * List the existing non-terminated jobs.
100
         *
101
         * @return A list of jobs.
102
         * @throws IOException
103
         *             If things go wrong.
104
         */
105
        default List<Job> listJobs() throws IOException {
UNCOV
106
                return listJobs(false);
×
107
        }
108

109
        /**
110
         * List the jobs, including the deleted ones.
111
         * <p>
112
         * <strong>NB:</strong> Care should be taken; this may produce a lot of
113
         * output.
114
         *
115
         * @return A stream of jobs.
116
         * @throws IOException
117
         *             If things go wrong.
118
         */
119
        default Stream<Job> listJobsWithDeleted() throws IOException {
UNCOV
120
                return listJobsWithDeleted(false);
×
121
        }
122

123
        /**
124
         * Create a job.
125
         *
126
         * @param createInstructions
127
         *            Describes the job to create.
128
         * @return A handle to the created job.
129
         * @throws IOException
130
         *             If job creation fails.
131
         */
132
        Job createJob(CreateJob createInstructions) throws IOException;
133

134
        /** The services offered relating to a Spalloc machine. */
135
        interface Machine {
136
                /**
137
                 * The machine's name. Never empty, never {@code null}.
138
                 *
139
                 * @return The name of the machine.
140
                 */
141
                String getName();
142

143
                /**
144
                 * The tags of the machine. If this includes "{@code default}", this is
145
                 * the machine that jobs will usually go to.
146
                 *
147
                 * @return The tags of the machine.
148
                 */
149
                List<String> getTags();
150

151
                /**
152
                 * The width of the machine.
153
                 *
154
                 * @return The width of the machine, in triads.
155
                 */
156
                int getWidth();
157

158
                /**
159
                 * The height of the machine.
160
                 *
161
                 * @return The height of the machine, in triads.
162
                 */
163
                int getHeight();
164

165
                /**
166
                 * The number of live boards.
167
                 *
168
                 * @return The (estimated) number of live boards in the machine.
169
                 */
170
                int getLiveBoardCount();
171

172
                /**
173
                 * What boards in the machine are dead?
174
                 *
175
                 * @return The dead boards of the machine.
176
                 */
177
                List<BoardCoords> getDeadBoards();
178

179
                /**
180
                 * What links in the machine are dead? Only links where both boards are
181
                 * alive.
182
                 *
183
                 * @return The dead links of the machine.
184
                 */
185
                List<DeadLink> getDeadLinks();
186

187
                /**
188
                 * Wait (for up to 30 seconds) until the state of the machine might have
189
                 * changed.
190
                 *
191
                 * @throws IOException
192
                 *             If communication with the server fails
193
                 */
194
                void waitForChange() throws IOException;
195

196
                /**
197
                 * Given logical triad coordinates, return more info about a board.
198
                 *
199
                 * @param coords
200
                 *            Triad coordinates
201
                 * @return Board information
202
                 * @throws FileNotFoundException
203
                 *             If the board doesn't exist.
204
                 * @throws IOException
205
                 *             If communication with the server fails
206
                 */
207
                WhereIs getBoard(@NotNull @Valid TriadCoords coords)
208
                                throws FileNotFoundException, IOException;
209

210
                /**
211
                 * Given physical coordinates, return more info about a board.
212
                 *
213
                 * @param coords
214
                 *            Physical coordinates.
215
                 * @return Board information
216
                 * @throws FileNotFoundException
217
                 *             If the board doesn't exist.
218
                 * @throws IOException
219
                 *             If communication with the server fails
220
                 */
221
                WhereIs getBoard(@NotNull @Valid PhysicalCoords coords)
222
                                throws FileNotFoundException, IOException;
223

224
                /**
225
                 * Given a <em>global</em> chip location, return more info about the
226
                 * board that contains it.
227
                 *
228
                 * @param chip
229
                 *            The chip location
230
                 * @return Board information
231
                 * @throws FileNotFoundException
232
                 *             If the board doesn't exist.
233
                 * @throws IOException
234
                 *             If communication with the server fails
235
                 */
236
                WhereIs getBoard(@NotNull @Valid HasChipLocation chip)
237
                                throws FileNotFoundException, IOException;
238

239
                /**
240
                 * Given an IP address, return more info about a board.
241
                 *
242
                 * @param address
243
                 *            Board IP address
244
                 * @return Board information
245
                 * @throws FileNotFoundException
246
                 *             If the board doesn't exist.
247
                 * @throws IOException
248
                 *             If communication with the server fails
249
                 */
250
                WhereIs getBoard(@IPAddress String address)
251
                                throws FileNotFoundException, IOException;
252
        }
253

254
        /**
255
         * The services offered relating to a Spalloc job. Jobs run on
256
         * {@linkplain Machine machines}, and have boards allocated to them while
257
         * they do so. Those boards (which will be connected) are a fundamental
258
         * resource that allows SpiNNaker programs to be run.
259
         */
260
        interface Job {
261
                /**
262
                 * Get a description of a job. Includes the state of the job.
263
                 *
264
                 * @param waitForChange
265
                 *            If {@code true}, will wait until the jobs may have
266
                 *            changed. (Best-effort only; waiting time is bounded at 30
267
                 *            seconds.)
268
                 * @return The job description &amp; state. Check the state to see
269
                 *         whether the job has had resources allocated yet.
270
                 * @throws IOException
271
                 *             If communication fails.
272
                 */
273
                JobDescription describe(boolean waitForChange) throws IOException;
274

275
                /**
276
                 * Get a description of a job. Includes the state of the job.
277
                 *
278
                 * @return The job description &amp; state. Check the state to see
279
                 *         whether the job has had resources allocated yet.
280
                 * @throws IOException
281
                 *             If communication fails.
282
                 */
283
                default JobDescription describe() throws IOException {
UNCOV
284
                        return describe(false);
×
285
                }
286

287
                /**
288
                 * Must be periodically called to prevent the service watchdog from
289
                 * culling the job.
290
                 *
291
                 * @throws IOException
292
                 *             If communication fails.
293
                 */
294
                void keepalive() throws IOException;
295

296
                /**
297
                 * Mark a job as deleted.
298
                 *
299
                 * @param reason
300
                 *            Why the job is to be deleted.
301
                 * @throws IOException
302
                 *             If communication fails.
303
                 */
304
                void delete(String reason) throws IOException;
305

306
                /**
307
                 * Get a description of what's been allocated to the job.
308
                 *
309
                 * @return a description of the allocated resources
310
                 * @throws IOException
311
                 *             If communication fails, the resources have not yet been
312
                 *             allocated, or the job is deleted.
313
                 */
314
                AllocatedMachine machine() throws IOException;
315

316
                /**
317
                 * Get whether the boards of the machine are all switched on.
318
                 *
319
                 * @return {@code true} iff the boards are all on.
320
                 * @throws IOException
321
                 *             If communication fails, the resources have not yet been
322
                 *             allocated, or the job is deleted.
323
                 */
324
                boolean getPower() throws IOException;
325

326
                /**
327
                 * Set the power state of the boards of the machine. Note that actually
328
                 * changing the power state of the boards may take some time.
329
                 *
330
                 * @param switchOn
331
                 *            {@code true} to switch the boards on, {@code false} to
332
                 *            switch them off.
333
                 * @return {@code true} iff the boards are all on.
334
                 * @throws IOException
335
                 *             If communication fails, the resources have not yet been
336
                 *             allocated, or the job is deleted.
337
                 */
338
                boolean setPower(boolean switchOn) throws IOException;
339

340
                /**
341
                 * Given the location of a chip within an allocation, return more info
342
                 * about a board.
343
                 *
344
                 * @param chip
345
                 *            Chip location (relative to the root of the allocation).
346
                 * @return Board information
347
                 * @throws FileNotFoundException
348
                 *             If the board doesn't exist or no boards are allocated to
349
                 *             the job currently.
350
                 * @throws IOException
351
                 *             If communication fails or the job is deleted.
352
                 */
353
                WhereIs whereIs(@NotNull @Valid HasChipLocation chip)
354
                                throws FileNotFoundException, IOException;
355

356
                /**
357
                 * Create a proxied transceiver for talking to the boards of the job.
358
                 * The transceiver will be configured so that it can talk to all the
359
                 * boards of the job and nothing else; the BMP(s) will <em>not</em> be
360
                 * accessible by this transceiver.
361
                 *
362
                 * @return The transceiver. It is the caller's responsibility to close
363
                 *         this transceiver at the right time.
364
                 * @throws IOException
365
                 *             If communication fails or the job is deleted.
366
                 * @throws InterruptedException
367
                 *             If interrupted waiting for the connection to be set up.
368
                 * @throws SpinnmanException
369
                 *             If transceiver construction fails.
370
                 */
371
                @MustBeClosed
372
                TransceiverInterface getTransceiver()
373
                                throws IOException, InterruptedException, SpinnmanException;
374

375
                /**
376
                 * Wait until the job's boards are powered on or the job is destroyed.
377
                 *
378
                 * @throws IOException
379
                 *             If communication fails.
380
                 */
381
                default void waitForPower() throws IOException {
UNCOV
382
                        var state = describe().getState();
×
383
                        while (state == State.QUEUED || state == State.POWER) {
×
UNCOV
384
                                state = describe(true).getState();
×
385
                        }
UNCOV
386
                }
×
387

388
                /**
389
                 * Write memory directly using the Spalloc API.
390
                 *
391
                 * @param chip The chip to write to
392
                 * @param baseAddress The base address to write to
393
                 * @param data The data to write
394
                 * @throws IOException
395
                 *             If communications fail.
396
                 * @throws SpallocServerException
397
                 *             If the spalloc server rejects the operation request.
398
                 * @throws InterruptedException
399
                 *             If interrupted while waiting.
400
                 */
401
                void writeMemory(HasChipLocation chip, MemoryLocation baseAddress,
402
                                ByteBuffer data)
403
                                throws IOException, SpallocServerException,        InterruptedException;
404

405
                /**
406
                 * Read memory directly using the Spalloc API.
407
                 *
408
                 * @param chip The chip to read from
409
                 * @param baseAddress The base address to read from
410
                 * @param length The number of bytes to read
411
                 * @return The data read
412
                 * @throws IOException
413
                 *             If communications fail.
414
                 * @throws SpallocServerException
415
                 *             If the spalloc server rejects the operation request.
416
                 * @throws InterruptedException
417
                 *             If interrupted while waiting.
418
                 */
419
                ByteBuffer readMemory(HasChipLocation chip, MemoryLocation baseAddress,
420
                                int length)
421
                                throws IOException, SpallocServerException, InterruptedException;
422
        }
423

424
        /**
425
         * Exception caused by the server sending an error.
426
         */
427
        class SpallocException extends RuntimeException {
428
                private static final long serialVersionUID = -1363689283367574333L;
429

430
                /** The HTTP response code that triggered the exception. */
431
                private final int responseCode;
432

433
                /**
434
                 * Create an instance.
435
                 *
436
                 * @param message
437
                 *            The message body of the error.
438
                 * @param responseCode
439
                 *            The HTTP response code that triggered the exception.
440
                 */
441
                public SpallocException(String message, int responseCode) {
UNCOV
442
                        super(message);
×
UNCOV
443
                        this.responseCode = responseCode;
×
UNCOV
444
                }
×
445

446
                SpallocException(InputStream stream, int responseCode)
447
                                throws IOException {
UNCOV
448
                        super(consume(stream));
×
UNCOV
449
                        this.responseCode = responseCode;
×
UNCOV
450
                }
×
451

452
                private static String consume(InputStream stream) throws IOException {
453
                        try {
UNCOV
454
                                return join("\n", readLines(stream, UTF_8));
×
455
                        } finally {
UNCOV
456
                                stream.close();
×
457
                        }
458
                }
459

460
                /**
461
                 * @return The HTTP response code that triggered the exception.
462
                 */
463
                public int getResponseCode() {
UNCOV
464
                        return responseCode;
×
465
                }
466
        }
467
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc