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

SpiNNakerManchester / JavaSpiNNaker / 6233274834

19 Sep 2023 08:46AM UTC coverage: 36.409% (-0.6%) from 36.982%
6233274834

Pull #658

github

dkfellows
Merge branch 'master' into java-17
Pull Request #658: Update Java version to 17

1656 of 1656 new or added lines in 260 files covered. (100.0%)

8373 of 22997 relevant lines covered (36.41%)

0.36 hits per line

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

47.06
/SpiNNaker-allocserv/src/main/java/uk/ac/manchester/spinnaker/alloc/compat/Utils.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.compat;
17

18
import static java.lang.Integer.parseInt;
19
import static java.lang.Thread.interrupted;
20
import static java.util.Objects.isNull;
21
import static org.slf4j.LoggerFactory.getLogger;
22
import static uk.ac.manchester.spinnaker.utils.UnitConstants.NSEC_PER_SEC;
23

24
import java.io.IOException;
25
import java.time.Instant;
26
import java.util.List;
27
import java.util.Map;
28
import java.util.concurrent.Callable;
29
import java.util.stream.Stream;
30

31
import org.slf4j.Logger;
32
import org.springframework.dao.DataAccessException;
33

34
import uk.ac.manchester.spinnaker.alloc.model.BoardCoords;
35
import uk.ac.manchester.spinnaker.alloc.model.DownLink;
36
import uk.ac.manchester.spinnaker.alloc.model.JobState;
37
import uk.ac.manchester.spinnaker.spalloc.messages.BoardCoordinates;
38
import uk.ac.manchester.spinnaker.spalloc.messages.BoardLink;
39
import uk.ac.manchester.spinnaker.spalloc.messages.State;
40

41
/**
42
 * Utility functions to support {@link V1CompatService}.
43
 *
44
 * @author Donal Fellows
45
 */
46
abstract class Utils {
47
        private static final Logger log = getLogger(V1CompatService.class);
1✔
48

49
        private Utils() {
50
        }
51

52
        /**
53
         * The notification handler task core implementation. This is
54
         * <em>designed</em> to be interrupted; the task does not complete until it
55
         * is interrupted or an exception is thrown!
56
         *
57
         * @author Donal Fellows
58
         */
59
        @FunctionalInterface
60
        interface Notifier {
61
                /**
62
                 * How to wait for an event and send a notification about it.
63
                 *
64
                 * @throws InterruptedException
65
                 *             If the wait is interrupted.
66
                 * @throws DataAccessException
67
                 *             If database access fails.
68
                 * @throws IOException
69
                 *             If network access fails.
70
                 */
71
                void waitAndNotify()
72
                                throws InterruptedException, DataAccessException, IOException;
73

74
                /**
75
                 * Wrap a notifier into a callable, doing some of the exception
76
                 * handling.
77
                 *
78
                 * @param notifier
79
                 *            The notifier to wrap.
80
                 * @return The wrapped notifier.
81
                 */
82
                static Callable<Void> toCallable(Notifier notifier) {
83
                        return () -> {
1✔
84
                                try {
85
                                        while (!interrupted()) {
1✔
86
                                                notifier.waitAndNotify();
1✔
87
                                        }
88
                                } catch (DataAccessException e) {
×
89
                                        log.error("SQL failure", e);
×
90
                                } catch (IOException e) {
×
91
                                        log.warn("failed to notify", e);
×
92
                                } catch (InterruptedException ignored) {
×
93
                                        // Nothing to do
94
                                } catch (RuntimeException e) {
×
95
                                        log.error("unexpected exception", e);
×
96
                                }
1✔
97
                                return null;
1✔
98
                        };
99
                }
100
        }
101

102
        /**
103
         * Parse a value as non-negative decimal.
104
         *
105
         * @param value
106
         *            The value to parse (must actually be a string or a number).
107
         * @return The decimal value.
108
         * @throws IllegalArgumentException
109
         *             If the object can't be converted to a number.
110
         */
111
        static Integer parseDec(Object value) {
112
                int n;
113
                if (isNull(value)) {
1✔
114
                        return null;
1✔
115
                } else if (value instanceof Number num) {
1✔
116
                        n = num.intValue();
1✔
117
                } else if (value instanceof String s) {
×
118
                        n = parseInt(s);
×
119
                } else {
120
                        throw new IllegalArgumentException(
×
121
                                        "needed a number, got a " + value.getClass().getName());
×
122
                }
123
                if (n < 0) {
1✔
124
                        throw new IllegalArgumentException("negative values not supported");
×
125
                }
126
                return n;
1✔
127
        }
128

129
        /**
130
         * Get an argument from an argument list.
131
         *
132
         * @param <T>
133
         *            The type of values in the list.
134
         * @param args
135
         *            The list containing the value.
136
         * @param index
137
         *            The index into the list.
138
         * @return The value.
139
         * @throws Oops
140
         *             If the list doesn't have a value at that index.
141
         */
142
        static <T> T getArgument(List<T> args, int index) {
143
                if (isNull(args) || index < 0 || index >= args.size()) {
1✔
144
                        throw new Oops("missing argument at index " + index);
×
145
                }
146
                return args.get(index);
1✔
147
        }
148

149
        /**
150
         * Get an argument from an argument map.
151
         *
152
         * @param <T>
153
         *            The type of values in the map.
154
         * @param kwargs
155
         *            The map containing the value.
156
         * @param index
157
         *            The key into the map.
158
         * @return The value.
159
         * @throws Oops
160
         *             If the map doesn't have a value with that key.
161
         */
162
        static <T> T getArgument(Map<String, T> kwargs, String index) {
163
                if (isNull(kwargs) || !kwargs.containsKey(index)) {
1✔
164
                        throw new Oops("missing keyword argument: " + index);
×
165
                }
166
                return kwargs.get(index);
1✔
167
        }
168

169
        /**
170
         * Parse a value as non-negative decimal.
171
         *
172
         * @param <T>
173
         *            The type of the values in the list (must actually be a
174
         *            string or a number or a supertype thereof).
175
         * @param args
176
         *            The list containing the value to parse.
177
         * @param index
178
         *            The index into the list.
179
         * @return The decimal value.
180
         */
181
        static <T> int parseDec(List<T> args, int index) {
182
                return parseDec(getArgument(args, index));
1✔
183
        }
184

185
        /**
186
         * Parse a value as non-negative decimal.
187
         *
188
         * @param <T>
189
         *            The type of the values in the map (must actually be a
190
         *            string or a number or a supertype thereof).
191
         * @param kwargs
192
         *            The map containing the value to parse.
193
         * @param index
194
         *            The index into the map.
195
         * @return The decimal value.
196
         */
197
        static <T> int parseDec(Map<String, T> kwargs, String index) {
198
                return parseDec(getArgument(kwargs, index));
1✔
199
        }
200

201
        /**
202
         * Convert an instant into an old-style timestamp.
203
         *
204
         * @param instant
205
         *            The instant to convert
206
         * @return The timestamp
207
         */
208
        static Double timestamp(Instant instant) {
209
                if (isNull(instant)) {
1✔
210
                        return null;
×
211
                }
212
                double ts = instant.getEpochSecond();
1✔
213
                ts += instant.getNano() / (double) NSEC_PER_SEC;
1✔
214
                return ts;
1✔
215
        }
216

217
        /**
218
         * Convert the state of a job.
219
         *
220
         * @param state
221
         *            The job state
222
         * @return The converted state.
223
         */
224
        static State state(JobState state) {
225
                // So trivial...
226
                return switch (state) {
1✔
227
                case QUEUED -> State.QUEUED;
1✔
228
                case POWER -> State.POWER;
×
229
                case READY -> State.READY;
×
230
                case DESTROYED -> State.DESTROYED;
×
231
                default -> State.UNKNOWN;
×
232
                };
233
        }
234

235
        /**
236
         * Convert a board coordinate into another form.
237
         *
238
         * @param coords
239
         *            The coordinate to convert.
240
         * @return The converted coordinate.
241
         */
242
        static BoardCoordinates board(BoardCoords coords) {
243
                return new BoardCoordinates(coords.x(), coords.y(), coords.z());
×
244
        }
245

246
        /**
247
         * Convert a down-link descriptor into another form.
248
         *
249
         * @param downLink
250
         *            The link descriptor to convert.
251
         * @return A stream of ends of the link.
252
         */
253
        static Stream<BoardLink> boardLinks(DownLink downLink) {
254
                var bl1 = new BoardLink(downLink.end1().board().x(),
×
255
                                downLink.end1().board().y(), downLink.end1().board().z(),
×
256
                                downLink.end1().direction().ordinal());
×
257

258
                var bl2 = new BoardLink(downLink.end2().board().x(),
×
259
                                downLink.end2().board().y(), downLink.end2().board().z(),
×
260
                                downLink.end2().direction().ordinal());
×
261

262
                return List.of(bl1, bl2).stream();
×
263
        }
264
}
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