1 package org.lsst.ccs.bus;
2
3
4
5 import org.lsst.ccs.utilities.beanutils.Optional;
6 import org.lsst.ccs.utilities.logging.Logger;
7 import org.lsst.ccs.utilities.tracers.Tracer;
8
9 import java.io.IOException;
10 import java.util.IdentityHashMap;
11 import java.util.List;
12 import java.util.concurrent.CopyOnWriteArrayList;
13
14
15
16
17
18
19
20
21
22
23
24
25
26 public class BusApplicationLayer {
27 protected final String subsystemName;
28 protected final BusMessagingLayer busMessagingLayer;
29 protected static Logger log = Logger.getLogger("org.lsst.ccs.bus.layer");
30
31
32
33
34
35
36 String token = java.util.UUID.randomUUID().toString();
37 private final MembershipMultiplexor membershipMultiplexor = new MembershipMultiplexor();
38
39
40
41
42
43
44
45
46
47
48
49 public BusApplicationLayer(String subsystemName, BusMessagingLayer busMessagingLayer) {
50 this.subsystemName = subsystemName;
51 this.busMessagingLayer = busMessagingLayer;
52 }
53
54 public String getToken() {
55 return token;
56 }
57
58
59
60
61
62
63 public void registerToCommand() throws IOException {
64 busMessagingLayer.register(subsystemName, Bus.COMMAND);
65 }
66
67
68
69
70
71
72 public void registerToStatus() throws IOException {
73 busMessagingLayer.register(subsystemName, Bus.STATUS);
74 }
75
76
77
78
79
80
81 public void registerToLog() throws IOException {
82 busMessagingLayer.register(subsystemName, Bus.LOG);
83 }
84
85
86
87
88
89
90
91
92
93
94
95 protected String[] parseDestination(String destination) {
96 String[] dests = destination.split(",");
97 for (int ix = 0; ix < dests.length; ix++) {
98 String dest = dests[ix];
99 if ("*".equals(dest)) {
100 dests = new String[0];
101 break;
102 }
103 if (dest.contains("/")) {
104 dests[ix] = dest.substring(0, dest.indexOf("/"));
105 }
106 }
107 return dests;
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public void sendCommand(Command cmd) throws IOException {
123 String[] destinations = parseDestination(cmd.getDestination());
124 cmd.setKey(token);
125 if (cmd.getOrigin() == null) {
126 cmd.setOrigin(subsystemName);
127 }
128 if (cmd.getCorrelId() == null) {
129
130 cmd.setCorrelId(java.util.UUID.randomUUID().toString());
131 }
132 busMessagingLayer.sendMessage(subsystemName, Bus.COMMAND, cmd, destinations);
133 }
134
135
136
137
138
139
140
141
142 public void sendStatus(Status status) throws IOException {
143 if (status.getOrigin() == null) {
144 status.setOrigin(subsystemName);
145 }
146 busMessagingLayer.sendMessage(subsystemName, Bus.STATUS, status);
147 }
148
149
150
151
152
153
154
155
156 public void sendLogEvent(LogEvent evt) throws IOException {
157 if (evt.getOrigin() == null) {
158 evt.setOrigin(subsystemName);
159 }
160 busMessagingLayer.sendMessage(subsystemName, Bus.LOG, evt);
161
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 public void reply(CommandAckOrReply cmd) throws IOException {
180
181
182
183
184
185 if (cmd.getOrigin() == null) {
186 cmd.setOrigin(subsystemName);
187 }
188
189
190
191
192
193 String destination = cmd.getDestination();
194
195
196
197
198
199
200 busMessagingLayer.sendMessage(subsystemName, Bus.COMMAND, cmd, destination);
201 }
202
203
204
205
206
207
208
209 IdentityHashMap<CommandListener, BusMessageForwarder> commandForwarderMap = new IdentityHashMap<>();
210 IdentityHashMap<LogListener, BusMessageForwarder> logForwarderMap = new IdentityHashMap<>();
211 IdentityHashMap<StatusListens, BusMessageForwarder> statusForwarderMap = new IdentityHashMap<>();
212
213 void addMembershipListener(BusMembershipListener l) {
214
215
216 membershipMultiplexor.addMembershipListener(l);
217 }
218
219 void removeMembershipListener(BusMembershipListener l) {
220 membershipMultiplexor.removeMembershipListener(l);
221 }
222
223
224
225
226 private class MembershipMultiplexor implements BusMembershipListener {
227
228
229 private final List<BusMembershipListener> listenerList = new CopyOnWriteArrayList<>();
230 private boolean registered = false;
231
232 private void addMembershipListener(BusMembershipListener l) {
233 synchronized (this) {
234 if (!registered) {
235 busMessagingLayer.setMembershipListener(this, Bus.COMMAND);
236 registered = true;
237 }
238 }
239 listenerList.add(l);
240 }
241
242 private void removeMembershipListener(BusMembershipListener l) {
243 listenerList.remove(l);
244 }
245
246 @Override
247 public void connecting(String agentName, String otherInfos) {
248 for (BusMembershipListener l : listenerList) {
249 l.connecting(agentName, otherInfos);
250 }
251 }
252
253 @Override
254 public void disconnecting(String agentName, String otherInfos) {
255 for (BusMembershipListener l : listenerList) {
256 l.disconnecting(agentName, otherInfos);
257 }
258 }
259
260 @Override
261 public void anormalEvent(Exception exc) {
262 for (BusMembershipListener l : listenerList) {
263 l.anormalEvent(exc);
264 }
265 }
266 }
267
268
269
270
271
272
273
274
275
276 protected class ForwarderToCommand implements BusMessageForwarder {
277 CommandListener listener;
278
279 ForwarderToCommand(CommandListener listener) {
280 this.listener = listener;
281 commandForwarderMap.put(listener, this);
282 }
283
284 @Override
285 public void update(BusMessage message) {
286 if (message instanceof CommandReply) {
287 listener.onReply((CommandReply) message);
288 } else if (message instanceof CommandAck) {
289 listener.onAck((CommandAck) message);
290 } else if (message instanceof Command) {
291 Command cmd = (Command) message;
292
293
294
295
296
297
298 try {
299 assert Tracer.trace("executing: " + cmd);
300 listener.onCommand(cmd);
301 } catch (Throwable throwable) {
302 log.error("on command :" + throwable);
303 }
304 }
305
306 }
307 }
308
309
310
311
312 public class ForwarderToStatus implements BusMessageForwarder {
313 final StatusListens listener;
314 final boolean isEncodedListener;
315 final boolean isKeyValueListener;
316 final boolean isDataListener;
317 final boolean isCrystallizedListener;
318
319 public ForwarderToStatus(StatusListens listener) {
320 this.listener = listener;
321 isEncodedListener = listener instanceof EncodedStatusListens;
322 isKeyValueListener = listener instanceof KeyValueStatusListener;
323 isDataListener = listener instanceof DataStatusListener;
324 isCrystallizedListener = listener instanceof SerializedDataStatusListener;
325 statusForwarderMap.put(listener, this);
326 }
327
328 @Override
329 public void update(BusMessage message) {
330 if (message instanceof EncodedDataStatus && isEncodedListener) {
331 EncodedDataStatus status = (EncodedDataStatus) message;
332 String source = status.getOrigin();
333 for (EncodedDataStatus dataStatus : status) {
334 long timeStamp = dataStatus.getDataTimestamp();
335 KVList list = dataStatus.getContent();
336 for (KeyData keyData : list) {
337 String key = keyData.getKey();
338 if (isDataListener) {
339 Optional<Object> optObj = keyData.getValue();
340 if (optObj.isPresent()) {
341 ((DataStatusListener) listener).onDataArrival(source, timeStamp, key, optObj.get());
342
343 }
344
345 }
346 if (isKeyValueListener) {
347 int id = keyData.hashCode();
348 List<KeyData> detailsList = keyData.getContentAsList();
349 for (KeyData detaileddata : detailsList) {
350 String complexKey = detaileddata.getKey();
351 Optional<Object> optional = detaileddata.getValue();
352 if (optional.isPresent()) {
353 ((KeyValueStatusListener) listener).onKeyValueStatusDecomposition(source, timeStamp, complexKey, optional.get(), id);
354 }
355 }
356 }
357 if (isCrystallizedListener) {
358 Optional<byte[]> crysta = keyData.getCrystallizedData();
359 if (crysta.isPresent()) {
360 ((SerializedDataStatusListener) listener).onSerializedDataArrival(source, timeStamp, key, crysta.get());
361 }
362 }
363 }
364
365 }
366
367
368 } else {
369 if (listener instanceof StatusListener) {
370 ((StatusListener) listener).onStatus(message);
371 }
372 }
373 }
374 }
375
376
377
378
379 protected class ForwarderToLog implements BusMessageForwarder {
380 LogListener listener;
381
382 ForwarderToLog(LogListener listener) {
383 this.listener = listener;
384 logForwarderMap.put(listener, this);
385 }
386
387 @Override
388 public void update(BusMessage message) {
389 if (message instanceof LogEvent) {
390 listener.onLog((LogEvent) message);
391 }
392 }
393 }
394
395
396
397
398
399
400 public void addCommandListener(CommandListener l) {
401 busMessagingLayer.addMessageListener(subsystemName, new ForwarderToCommand(l), Bus.COMMAND);
402 }
403
404
405
406
407
408
409
410 public void removeCommandListener(CommandListener l) {
411 BusMessageForwarder forwarder = commandForwarderMap.remove(l);
412 if (forwarder != null) {
413 busMessagingLayer.removeMessageListener(subsystemName, forwarder, Bus.COMMAND);
414 } else {
415
416 }
417 }
418
419
420
421
422
423
424 public void addStatusListener(StatusListens l) {
425 busMessagingLayer.addMessageListener(subsystemName, new ForwarderToStatus(l), Bus.STATUS);
426 }
427
428 public void removeStatusListener(StatusListens l) {
429 BusMessageForwarder forwarder = statusForwarderMap.remove(l);
430 if (forwarder != null) {
431 busMessagingLayer.removeMessageListener(subsystemName, forwarder, Bus.STATUS);
432 } else {
433
434 }
435
436 }
437
438
439
440
441
442
443 public void addLogListener(LogListener l) {
444 busMessagingLayer.addMessageListener(subsystemName, new ForwarderToLog(l), Bus.LOG);
445 }
446
447 public void removeLogListener(LogListener l) {
448 BusMessageForwarder forwarder = logForwarderMap.remove(l);
449 if (forwarder != null) {
450 busMessagingLayer.removeMessageListener(subsystemName, forwarder, Bus.LOG);
451 } else {
452
453 }
454
455 }
456
457
458
459
460
461 public List<String> connectedToCommand() {
462 return busMessagingLayer.getConnectedNames(Bus.COMMAND) ;
463 }
464
465
466
467
468
469 public void close() {
470 busMessagingLayer.closeFor(subsystemName);
471 }
472 }