Browse Source

Synchronization of device connect processing in gateways

pull/2694/head
Andrii Shvaika 7 years ago
parent
commit
79b4411c69
  1. 74
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java

74
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -69,7 +69,8 @@ public class GatewaySessionHandler {
private final TransportService transportService; private final TransportService transportService;
private final DeviceInfoProto gateway; private final DeviceInfoProto gateway;
private final UUID sessionId; private final UUID sessionId;
private final Map<String, GatewayDeviceSessionCtx> devices; private final ConcurrentMap<String, GatewayDeviceSessionCtx> devices;
private final ConcurrentMap<String, SettableFuture<GatewayDeviceSessionCtx>> deviceFutures;
private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap; private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap;
private final ChannelHandlerContext channel; private final ChannelHandlerContext channel;
private final DeviceSessionCtx deviceSessionCtx; private final DeviceSessionCtx deviceSessionCtx;
@ -81,6 +82,7 @@ public class GatewaySessionHandler {
this.gateway = deviceSessionCtx.getDeviceInfo(); this.gateway = deviceSessionCtx.getDeviceInfo();
this.sessionId = sessionId; this.sessionId = sessionId;
this.devices = new ConcurrentHashMap<>(); this.devices = new ConcurrentHashMap<>();
this.deviceFutures = new ConcurrentHashMap<>();
this.mqttQoSMap = deviceSessionCtx.getMqttQoSMap(); this.mqttQoSMap = deviceSessionCtx.getMqttQoSMap();
this.channel = deviceSessionCtx.getChannel(); this.channel = deviceSessionCtx.getChannel();
} }
@ -106,35 +108,51 @@ public class GatewaySessionHandler {
} }
private ListenableFuture<GatewayDeviceSessionCtx> onDeviceConnect(String deviceName, String deviceType) { private ListenableFuture<GatewayDeviceSessionCtx> onDeviceConnect(String deviceName, String deviceType) {
SettableFuture<GatewayDeviceSessionCtx> future = SettableFuture.create(); SettableFuture<GatewayDeviceSessionCtx> future;
GatewayDeviceSessionCtx result = devices.get(deviceName); GatewayDeviceSessionCtx result = devices.get(deviceName);
if (result == null) { if (result == null) {
transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder() synchronized (deviceFutures) {
.setDeviceName(deviceName) future = deviceFutures.get(deviceName);
.setDeviceType(deviceType) if (future == null) {
.setGatewayIdMSB(gateway.getDeviceIdMSB()) final SettableFuture<GatewayDeviceSessionCtx> futureToSet = SettableFuture.create();
.setGatewayIdLSB(gateway.getDeviceIdLSB()).build(), deviceFutures.put(deviceName, futureToSet);
new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg>() { future = futureToSet;
@Override try {
public void onSuccess(GetOrCreateDeviceFromGatewayResponseMsg msg) { transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder()
GatewayDeviceSessionCtx deviceSessionCtx = new GatewayDeviceSessionCtx(GatewaySessionHandler.this, msg.getDeviceInfo(), mqttQoSMap); .setDeviceName(deviceName)
if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { .setDeviceType(deviceType)
SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); .setGatewayIdMSB(gateway.getDeviceIdMSB())
transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx); .setGatewayIdLSB(gateway.getDeviceIdLSB()).build(),
transportService.process(deviceSessionInfo, DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg>() {
transportService.process(deviceSessionInfo, TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), null); @Override
transportService.process(deviceSessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), null); public void onSuccess(GetOrCreateDeviceFromGatewayResponseMsg msg) {
} GatewayDeviceSessionCtx deviceSessionCtx = new GatewayDeviceSessionCtx(GatewaySessionHandler.this, msg.getDeviceInfo(), mqttQoSMap);
future.set(devices.get(deviceName)); if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) {
} SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo();
transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx);
@Override transportService.process(deviceSessionInfo, DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null);
public void onError(Throwable e) { transportService.process(deviceSessionInfo, TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), null);
log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e); transportService.process(deviceSessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), null);
future.setException(e); }
} futureToSet.set(devices.get(deviceName));
}); deviceFutures.remove(deviceName);
}
@Override
public void onError(Throwable e) {
log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e);
futureToSet.setException(e);
deviceFutures.remove(deviceName);
}
});
} catch (Throwable e) {
deviceFutures.remove(deviceName);
throw e;
}
}
}
} else { } else {
future = SettableFuture.create();
future.set(result); future.set(result);
} }
return future; return future;

Loading…
Cancel
Save