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

SpiNNakerManchester / JavaSpiNNaker / 14556105732

21 Mar 2025 04:17PM UTC coverage: 38.266%. Remained the same
14556105732

push

github

web-flow
Merge pull request #1222 from SpiNNakerManchester/more_spalloc_rest_calls

More spalloc rest calls

70 of 815 new or added lines in 33 files covered. (8.59%)

1689 existing lines in 35 files now uncovered.

9193 of 24024 relevant lines covered (38.27%)

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.ChipLocation;
35
import uk.ac.manchester.spinnaker.machine.CoreLocation;
36
import uk.ac.manchester.spinnaker.machine.HasChipLocation;
37
import uk.ac.manchester.spinnaker.machine.HasCoreLocation;
38
import uk.ac.manchester.spinnaker.machine.MemoryLocation;
39
import uk.ac.manchester.spinnaker.machine.board.PhysicalCoords;
40
import uk.ac.manchester.spinnaker.machine.board.TriadCoords;
41
import uk.ac.manchester.spinnaker.machine.tags.IPTag;
42
import uk.ac.manchester.spinnaker.messages.model.Version;
43
import uk.ac.manchester.spinnaker.transceiver.SpinnmanException;
44
import uk.ac.manchester.spinnaker.transceiver.TransceiverInterface;
45
import uk.ac.manchester.spinnaker.utils.validation.IPAddress;
46

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

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

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

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

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

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

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

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

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

154
                /**
155
                 * The width of the machine.
156
                 *
157
                 * @return The width of the machine, in triads.
158
                 */
159
                int getWidth();
160

161
                /**
162
                 * The height of the machine.
163
                 *
164
                 * @return The height of the machine, in triads.
165
                 */
166
                int getHeight();
167

168
                /**
169
                 * The number of live boards.
170
                 *
171
                 * @return The (estimated) number of live boards in the machine.
172
                 */
173
                int getLiveBoardCount();
174

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

391
                /**
392
                 * Write memory directly using the Spalloc API.
393
                 *
394
                 * @param chip The chip to write to
395
                 * @param baseAddress The base address to write to
396
                 * @param data The data to write
397
                 * @throws IOException
398
                 *             If communications fail.
399
                 */
400
                void writeMemory(HasChipLocation chip, MemoryLocation baseAddress,
401
                                ByteBuffer data) throws IOException;
402

403
                /**
404
                 * Read memory directly using the Spalloc API.
405
                 *
406
                 * @param chip The chip to read from
407
                 * @param baseAddress The base address to read from
408
                 * @param length The number of bytes to read
409
                 * @return The data read
410
                 * @throws IOException
411
                 *             If communications fail.
412
                 */
413
                ByteBuffer readMemory(HasChipLocation chip, MemoryLocation baseAddress,
414
                                int length) throws IOException;
415

416
                /**
417
                 * Fast write data directly with a job.  Assumes it has been set up.
418
                 *
419
                 * @param gathererCore The core to use on the Ethernet chip.
420
                 * @param iptag The tag ID to use for reading responses.
421
                 * @param chip The chip to write to.
422
                 * @param baseAddress The base address to write to.
423
                 * @param data The data to write.
424
                 *
425
                 * @throws IOException
426
                 *             If communications fail.
427
                 */
428
                void fastWriteData(CoreLocation gathererCore,
429
                                IPTag iptag, HasChipLocation chip, MemoryLocation baseAddress,
430
                                ByteBuffer data) throws IOException;
431

432
                /**
433
                 * Fast read data directly with a job.  Assumes it has been set up.
434
                 *
435
                 * @param gathererChip The chip where the gatherer core is.
436
                 * @param iptag The Tag ID to use for reading responses.
437
                 * @param monitorCore The monitor core to read from.
438
                 * @param baseAddress The SDRAM address to read from.
439
                 * @param length The number of bytes to read.
440
                 * @return The data read.
441
                 * @throws IOException If communications fail.
442
                 */
443
                ByteBuffer fastReadData(ChipLocation gathererChip,
444
                                IPTag iptag, HasCoreLocation monitorCore,
445
                                MemoryLocation baseAddress, int length) throws IOException;
446
        }
447

448
        /**
449
         * Exception caused by the server sending an error.
450
         */
451
        class SpallocException extends RuntimeException {
452
                private static final long serialVersionUID = -1363689283367574333L;
453

454
                /** The HTTP response code that triggered the exception. */
455
                private final int responseCode;
456

457
                /**
458
                 * Create an instance.
459
                 *
460
                 * @param message
461
                 *            The message body of the error.
462
                 * @param responseCode
463
                 *            The HTTP response code that triggered the exception.
464
                 */
465
                public SpallocException(String message, int responseCode) {
UNCOV
466
                        super(message);
×
UNCOV
467
                        this.responseCode = responseCode;
×
UNCOV
468
                }
×
469

470
                SpallocException(InputStream stream, int responseCode)
471
                                throws IOException {
UNCOV
472
                        super(consume(stream));
×
UNCOV
473
                        this.responseCode = responseCode;
×
UNCOV
474
                }
×
475

476
                private static String consume(InputStream stream) throws IOException {
477
                        try {
UNCOV
478
                                return join("\n", readLines(stream, UTF_8));
×
479
                        } finally {
UNCOV
480
                                stream.close();
×
481
                        }
482
                }
483

484
                /**
485
                 * @return The HTTP response code that triggered the exception.
486
                 */
487
                public int getResponseCode() {
UNCOV
488
                        return responseCode;
×
489
                }
490
        }
491
}
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