Commit a38ee80e0957d52bc21f0a201b081edf4d3420f2
1 parent
79b4411c
Refactoring of device creation using gateway
Showing
1 changed file
with
62 additions
and
42 deletions
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 6 | * You may obtain a copy of the License at |
7 | 7 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | 9 | * |
10 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
... | ... | @@ -54,6 +54,8 @@ import java.util.Set; |
54 | 54 | import java.util.UUID; |
55 | 55 | import java.util.concurrent.ConcurrentHashMap; |
56 | 56 | import java.util.concurrent.ConcurrentMap; |
57 | +import java.util.concurrent.locks.Lock; | |
58 | +import java.util.concurrent.locks.ReentrantLock; | |
57 | 59 | |
58 | 60 | /** |
59 | 61 | * Created by ashvayka on 19.01.17. |
... | ... | @@ -69,6 +71,7 @@ public class GatewaySessionHandler { |
69 | 71 | private final TransportService transportService; |
70 | 72 | private final DeviceInfoProto gateway; |
71 | 73 | private final UUID sessionId; |
74 | + private final Lock deviceCreationLock = new ReentrantLock(); | |
72 | 75 | private final ConcurrentMap<String, GatewayDeviceSessionCtx> devices; |
73 | 76 | private final ConcurrentMap<String, SettableFuture<GatewayDeviceSessionCtx>> deviceFutures; |
74 | 77 | private final ConcurrentMap<MqttTopicMatcher, Integer> mqttQoSMap; |
... | ... | @@ -108,53 +111,70 @@ public class GatewaySessionHandler { |
108 | 111 | } |
109 | 112 | |
110 | 113 | private ListenableFuture<GatewayDeviceSessionCtx> onDeviceConnect(String deviceName, String deviceType) { |
111 | - SettableFuture<GatewayDeviceSessionCtx> future; | |
112 | 114 | GatewayDeviceSessionCtx result = devices.get(deviceName); |
113 | 115 | if (result == null) { |
114 | - synchronized (deviceFutures) { | |
115 | - future = deviceFutures.get(deviceName); | |
116 | - if (future == null) { | |
117 | - final SettableFuture<GatewayDeviceSessionCtx> futureToSet = SettableFuture.create(); | |
118 | - deviceFutures.put(deviceName, futureToSet); | |
119 | - future = futureToSet; | |
120 | - try { | |
121 | - transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder() | |
122 | - .setDeviceName(deviceName) | |
123 | - .setDeviceType(deviceType) | |
124 | - .setGatewayIdMSB(gateway.getDeviceIdMSB()) | |
125 | - .setGatewayIdLSB(gateway.getDeviceIdLSB()).build(), | |
126 | - new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg>() { | |
127 | - @Override | |
128 | - public void onSuccess(GetOrCreateDeviceFromGatewayResponseMsg msg) { | |
129 | - GatewayDeviceSessionCtx deviceSessionCtx = new GatewayDeviceSessionCtx(GatewaySessionHandler.this, msg.getDeviceInfo(), mqttQoSMap); | |
130 | - if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { | |
131 | - SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); | |
132 | - transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx); | |
133 | - transportService.process(deviceSessionInfo, DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); | |
134 | - transportService.process(deviceSessionInfo, TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), null); | |
135 | - transportService.process(deviceSessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), null); | |
136 | - } | |
137 | - futureToSet.set(devices.get(deviceName)); | |
138 | - deviceFutures.remove(deviceName); | |
139 | - } | |
140 | - | |
141 | - @Override | |
142 | - public void onError(Throwable e) { | |
143 | - log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e); | |
144 | - futureToSet.setException(e); | |
145 | - deviceFutures.remove(deviceName); | |
146 | - } | |
147 | - }); | |
148 | - } catch (Throwable e) { | |
149 | - deviceFutures.remove(deviceName); | |
150 | - throw e; | |
151 | - } | |
116 | + deviceCreationLock.lock(); | |
117 | + try { | |
118 | + result = devices.get(deviceName); | |
119 | + if (result == null) { | |
120 | + return getDeviceCreationFuture(deviceName, deviceType); | |
121 | + } else { | |
122 | + return toCompletedFuture(result); | |
152 | 123 | } |
124 | + } finally { | |
125 | + deviceCreationLock.unlock(); | |
153 | 126 | } |
154 | 127 | } else { |
155 | - future = SettableFuture.create(); | |
156 | - future.set(result); | |
128 | + return toCompletedFuture(result); | |
157 | 129 | } |
130 | + } | |
131 | + | |
132 | + private ListenableFuture<GatewayDeviceSessionCtx> getDeviceCreationFuture(String deviceName, String deviceType) { | |
133 | + SettableFuture<GatewayDeviceSessionCtx> future = deviceFutures.get(deviceName); | |
134 | + if (future == null) { | |
135 | + final SettableFuture<GatewayDeviceSessionCtx> futureToSet = SettableFuture.create(); | |
136 | + deviceFutures.put(deviceName, futureToSet); | |
137 | + try { | |
138 | + transportService.process(GetOrCreateDeviceFromGatewayRequestMsg.newBuilder() | |
139 | + .setDeviceName(deviceName) | |
140 | + .setDeviceType(deviceType) | |
141 | + .setGatewayIdMSB(gateway.getDeviceIdMSB()) | |
142 | + .setGatewayIdLSB(gateway.getDeviceIdLSB()).build(), | |
143 | + new TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg>() { | |
144 | + @Override | |
145 | + public void onSuccess(GetOrCreateDeviceFromGatewayResponseMsg msg) { | |
146 | + GatewayDeviceSessionCtx deviceSessionCtx = new GatewayDeviceSessionCtx(GatewaySessionHandler.this, msg.getDeviceInfo(), mqttQoSMap); | |
147 | + if (devices.putIfAbsent(deviceName, deviceSessionCtx) == null) { | |
148 | + SessionInfoProto deviceSessionInfo = deviceSessionCtx.getSessionInfo(); | |
149 | + transportService.registerAsyncSession(deviceSessionInfo, deviceSessionCtx); | |
150 | + transportService.process(deviceSessionInfo, DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN), null); | |
151 | + transportService.process(deviceSessionInfo, TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), null); | |
152 | + transportService.process(deviceSessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.getDefaultInstance(), null); | |
153 | + } | |
154 | + futureToSet.set(devices.get(deviceName)); | |
155 | + deviceFutures.remove(deviceName); | |
156 | + } | |
157 | + | |
158 | + @Override | |
159 | + public void onError(Throwable e) { | |
160 | + log.warn("[{}] Failed to process device connect command: {}", sessionId, deviceName, e); | |
161 | + futureToSet.setException(e); | |
162 | + deviceFutures.remove(deviceName); | |
163 | + } | |
164 | + }); | |
165 | + return futureToSet; | |
166 | + } catch (Throwable e) { | |
167 | + deviceFutures.remove(deviceName); | |
168 | + throw e; | |
169 | + } | |
170 | + } else { | |
171 | + return future; | |
172 | + } | |
173 | + } | |
174 | + | |
175 | + private ListenableFuture<GatewayDeviceSessionCtx> toCompletedFuture(GatewayDeviceSessionCtx result) { | |
176 | + SettableFuture<GatewayDeviceSessionCtx> future = SettableFuture.create(); | |
177 | + future.set(result); | |
158 | 178 | return future; |
159 | 179 | } |
160 | 180 | ... | ... |