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

SpiNNakerManchester / JavaSpiNNaker / 13520271443

25 Feb 2025 11:34AM UTC coverage: 38.48% (-0.03%) from 38.51%
13520271443

push

github

rowleya
Fix tabs

675 of 2950 new or added lines in 17 files covered. (22.88%)

9 existing lines in 2 files now uncovered.

9182 of 23862 relevant lines covered (38.48%)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

435
        /**
436
         * Exception caused by the server sending an error.
437
         */
438
        class SpallocException extends RuntimeException {
439
                private static final long serialVersionUID = -1363689283367574333L;
440

441
                /** The HTTP response code that triggered the exception. */
442
                private final int responseCode;
443

444
                /**
445
                 * Create an instance.
446
                 *
447
                 * @param message
448
                 *            The message body of the error.
449
                 * @param responseCode
450
                 *            The HTTP response code that triggered the exception.
451
                 */
452
                public SpallocException(String message, int responseCode) {
NEW
453
                        super(message);
×
NEW
454
                        this.responseCode = responseCode;
×
NEW
455
                }
×
456

457
                SpallocException(InputStream stream, int responseCode)
458
                                throws IOException {
NEW
459
                        super(consume(stream));
×
NEW
460
                        this.responseCode = responseCode;
×
NEW
461
                }
×
462

463
                private static String consume(InputStream stream) throws IOException {
464
                        try {
NEW
465
                                return join("\n", readLines(stream, UTF_8));
×
466
                        } finally {
NEW
467
                                stream.close();
×
468
                        }
469
                }
470

471
                /**
472
                 * @return The HTTP response code that triggered the exception.
473
                 */
474
                public int getResponseCode() {
NEW
475
                        return responseCode;
×
476
                }
477
        }
478
}
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