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 }