1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.openr66.protocol.networkhandler;
21
22 import io.netty.channel.Channel;
23 import org.waarp.common.future.WaarpLock;
24 import org.waarp.common.logging.SysErrLogger;
25 import org.waarp.common.logging.WaarpLogger;
26 import org.waarp.common.logging.WaarpLoggerFactory;
27 import org.waarp.common.lru.ConcurrentUtility;
28 import org.waarp.openr66.context.ErrorCode;
29 import org.waarp.openr66.context.R66Result;
30 import org.waarp.openr66.context.R66Session;
31 import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
32 import org.waarp.openr66.database.data.DbTaskRunner;
33 import org.waarp.openr66.database.data.DbTaskRunner.TASKSTEP;
34 import org.waarp.openr66.protocol.configuration.Configuration;
35 import org.waarp.openr66.protocol.exception.OpenR66ProtocolRemoteShutdownException;
36 import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException;
37 import org.waarp.openr66.protocol.localhandler.LocalChannelReference;
38
39 import java.net.InetSocketAddress;
40 import java.net.SocketAddress;
41 import java.util.ArrayList;
42 import java.util.Set;
43 import java.util.concurrent.TimeUnit;
44
45 import static org.waarp.openr66.protocol.configuration.Configuration.*;
46
47
48
49
50
51 public class NetworkChannelReference {
52
53
54
55 private static final WaarpLogger logger =
56 WaarpLoggerFactory.getLogger(NetworkChannelReference.class);
57
58 private static final LocalChannelReference[] LCR_0_LENGTH =
59 new LocalChannelReference[0];
60
61
62
63
64 protected boolean isShuttingDown;
65
66
67
68 private final Set<LocalChannelReference> localChannelReferences =
69 ConcurrentUtility.newConcurrentSet();
70
71
72
73 protected final Channel channel;
74
75
76
77 protected final SocketAddress networkAddress;
78
79
80
81 private final String hostAddress;
82
83
84
85 private String hostId;
86
87
88
89 protected ClientNetworkChannels clientNetworkChannels;
90
91
92
93 protected final WaarpLock lock;
94
95
96
97 private long lastTimeUsed = System.currentTimeMillis();
98
99
100
101 private final boolean isSSL;
102
103 public NetworkChannelReference(final Channel networkChannel,
104 final WaarpLock lock, final boolean isSSL) {
105 channel = networkChannel;
106 networkAddress = channel.remoteAddress();
107 hostAddress =
108 ((InetSocketAddress) networkAddress).getAddress().getHostAddress();
109 this.lock = lock;
110 this.isSSL = isSSL;
111 }
112
113 public NetworkChannelReference(final SocketAddress address,
114 final WaarpLock lock, final boolean isSSL) {
115 channel = null;
116 networkAddress = address;
117 hostAddress =
118 ((InetSocketAddress) networkAddress).getAddress().getHostAddress();
119 this.lock = lock;
120 this.isSSL = isSSL;
121 }
122
123 public final boolean isSSL() {
124 return isSSL;
125 }
126
127 public final void add(final LocalChannelReference localChannel)
128 throws OpenR66ProtocolRemoteShutdownException {
129
130 if (isShuttingDown) {
131 throw new OpenR66ProtocolRemoteShutdownException(
132 "Current NetworkChannelReference is closed");
133 }
134 use();
135 localChannelReferences.add(localChannel);
136 }
137
138
139
140
141 public final void use() {
142 if (!isShuttingDown) {
143 lastTimeUsed = System.currentTimeMillis();
144 }
145 }
146
147
148
149
150
151
152 public final boolean useIfUsed() {
153 if (!isShuttingDown && !localChannelReferences.isEmpty()) {
154 lastTimeUsed = System.currentTimeMillis();
155 return true;
156 }
157 return false;
158 }
159
160
161
162
163
164
165 public final void closeAndRemove(final LocalChannelReference localChannel) {
166 if (!localChannel.getFutureRequest().isDone()) {
167 localChannel.close();
168 }
169 remove(localChannel);
170 }
171
172
173
174
175
176
177 public final void remove(final LocalChannelReference localChannel) {
178 localChannelReferences.remove(localChannel);
179
180 }
181
182
183
184
185 public final void shutdownAllLocalChannels() {
186 lock.lock(Configuration.WAITFORNETOP, TimeUnit.MILLISECONDS);
187 try {
188 logger.info("Will shutdown all local channels");
189 isShuttingDown = true;
190 final LocalChannelReference[] localChannelReferenceArray =
191 localChannelReferences.toArray(LCR_0_LENGTH);
192 final ArrayList<LocalChannelReference> toCloseLater =
193 new ArrayList<LocalChannelReference>();
194 for (final LocalChannelReference localChannelReference : localChannelReferenceArray) {
195 localChannelReference.getFutureRequest().awaitOrInterruptible(
196 Configuration.configuration.getTimeoutCon() / 3);
197 if (!localChannelReference.getFutureRequest().isDone()) {
198 localChannelReference.getFutureValidRequest().awaitOrInterruptible(
199 Configuration.configuration.getTimeoutCon() / 3);
200 if (localChannelReference.getFutureValidRequest().isDone() &&
201 localChannelReference.getFutureValidRequest().isFailed()) {
202 toCloseLater.add(localChannelReference);
203 continue;
204 } else {
205 final R66Result finalValue =
206 new R66Result(localChannelReference.getSession(), true,
207 ErrorCode.Shutdown, null);
208 if (localChannelReference.getSession() != null) {
209 try {
210 localChannelReference.getSession()
211 .tryFinalizeRequest(finalValue);
212 } catch (final OpenR66RunnerErrorException ignored) {
213
214 } catch (final OpenR66ProtocolSystemException ignored) {
215
216 }
217 }
218 }
219 }
220 localChannelReference.close();
221 }
222 try {
223 Thread.sleep(Configuration.WAITFORNETOP);
224 } catch (final InterruptedException e) {
225 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
226 }
227 for (final LocalChannelReference localChannelReference : toCloseLater) {
228 localChannelReference.getFutureRequest().awaitOrInterruptible(
229 Configuration.configuration.getTimeoutCon() / 3);
230 localChannelReference.close();
231 }
232 toCloseLater.clear();
233 } finally {
234 lock.unlock();
235 }
236 }
237
238
239
240
241
242
243 public final boolean isLastLocalChannelActive(
244 final LocalChannelReference localChannelReference) {
245 final boolean someActive = isSomeLocalChannelsActive();
246 return
247 (someActive && localChannelReferences.contains(localChannelReference) &&
248 localChannelReferences.size() == 1) ||
249 localChannelReferences.isEmpty();
250 }
251
252
253
254
255 public final long shutdownAllowed() {
256 lock.lock(Configuration.WAITFORNETOP, TimeUnit.MILLISECONDS);
257 try {
258 logger.debug("NC count: {}", this);
259 if (nbLocalChannels() <= 0) {
260 boolean reallyShutdownNetwork = true;
261 for (int i = 0; i < RETRYNB; i++) {
262 try {
263 Thread.sleep(RETRYINMS);
264 } catch (final InterruptedException e) {
265 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
266 }
267 if (nbLocalChannels() != 0) {
268 reallyShutdownNetwork = false;
269 break;
270 }
271 }
272 if (reallyShutdownNetwork) {
273 long time =
274 checkLastTime(Configuration.configuration.getTimeoutCon() * 2);
275 if (time > Configuration.RETRYINMS &&
276 Configuration.configuration.isTimerCloseReady()) {
277 logger.debug("NC reschedule at {} : {}", time, this);
278
279 time = (time / 10) * 10 + 100;
280 return time;
281 }
282 logger.info("Closing NETWORK channel {}", this);
283 return 0;
284 } else {
285 use();
286 logger.debug("Ignore closing Network channel");
287 return -1;
288 }
289 }
290 return -1;
291 } finally {
292 lock.unlock();
293 }
294 }
295
296 public final void lockNetwork() {
297 lock.lock(Configuration.WAITFORNETOP, TimeUnit.MILLISECONDS);
298 }
299
300 public final void unlockNetwork() {
301 lock.unlock();
302 }
303
304 public final int nbLocalChannels() {
305 return localChannelReferences.size();
306 }
307
308
309
310
311 public final boolean isSomeLocalChannelsActive() {
312 lock.lock(Configuration.WAITFORNETOP, TimeUnit.MILLISECONDS);
313 try {
314 for (final LocalChannelReference localChannelReference : localChannelReferences) {
315 final R66Session session = localChannelReference.getSession();
316 if (session != null) {
317 final DbTaskRunner runner = session.getRunner();
318 if (runner != null && !runner.isFinished() &&
319 runner.getGlobalStep() != TASKSTEP.NOTASK) {
320 return true;
321 }
322 }
323 }
324 return false;
325 } finally {
326 lock.unlock();
327 }
328 }
329
330 @Override
331 public final String toString() {
332 return "NC: " + hostId + ':' + (channel != null && channel.isActive()) +
333 ' ' + networkAddress + " Count: " + localChannelReferences.size();
334 }
335
336 @Override
337 public final boolean equals(final Object obj) {
338 if (obj instanceof NetworkChannelReference) {
339 final NetworkChannelReference obj2 = (NetworkChannelReference) obj;
340 if (obj2.channel == null || channel == null) {
341 return false;
342 }
343 return obj2.channel.id().compareTo(channel.id()) == 0;
344 }
345 return false;
346 }
347
348 @Override
349 public final int hashCode() {
350 if (channel == null) {
351 return Integer.MIN_VALUE;
352 }
353 return channel.id().hashCode();
354 }
355
356
357
358
359 public final int getSocketHashCode() {
360 return networkAddress.hashCode();
361 }
362
363
364
365
366
367
368 public final int getAddressHashCode() {
369 return hostAddress.hashCode();
370 }
371
372
373
374
375
376
377
378
379
380
381
382 public final long checkLastTime(final long delay) {
383 return lastTimeUsed + delay - System.currentTimeMillis();
384 }
385
386
387
388
389 public final boolean isShuttingDown() {
390 return isShuttingDown;
391 }
392
393
394
395
396 public final Channel channel() {
397 return channel;
398 }
399
400
401
402
403 public final String getHostId() {
404 return hostId;
405 }
406
407
408
409
410 public final void setHostId(final String hostId) {
411 this.hostId = hostId;
412 }
413
414
415
416
417 public final long getLastTimeUsed() {
418 return lastTimeUsed;
419 }
420
421 }