View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.oio;
17  
18  import io.netty.channel.AbstractChannel;
19  import io.netty.channel.Channel;
20  import io.netty.channel.ChannelPromise;
21  import io.netty.channel.EventLoop;
22  import io.netty.channel.ThreadPerChannelEventLoop;
23  
24  import java.net.SocketAddress;
25  
26  /**
27   * Abstract base class for {@link Channel} implementations that use Old-Blocking-IO
28   *
29   * @deprecated use NIO / EPOLL / KQUEUE transport.
30   */
31  @Deprecated
32  public abstract class AbstractOioChannel extends AbstractChannel {
33  
34      protected static final int SO_TIMEOUT = 1000;
35  
36      boolean readPending;
37      private final Runnable readTask = new Runnable() {
38          @Override
39          public void run() {
40              doRead();
41          }
42      };
43      private final Runnable clearReadPendingRunnable = new Runnable() {
44          @Override
45          public void run() {
46              readPending = false;
47          }
48      };
49  
50      /**
51       * @see AbstractChannel#AbstractChannel(Channel)
52       */
53      protected AbstractOioChannel(Channel parent) {
54          super(parent);
55      }
56  
57      @Override
58      protected AbstractUnsafe newUnsafe() {
59          return new DefaultOioUnsafe();
60      }
61  
62      private final class DefaultOioUnsafe extends AbstractUnsafe {
63          @Override
64          public void connect(
65                  final SocketAddress remoteAddress,
66                  final SocketAddress localAddress, final ChannelPromise promise) {
67              if (!promise.setUncancellable() || !ensureOpen(promise)) {
68                  return;
69              }
70  
71              try {
72                  boolean wasActive = isActive();
73                  doConnect(remoteAddress, localAddress);
74  
75                  // Get the state as trySuccess() may trigger an ChannelFutureListener that will close the Channel.
76                  // We still need to ensure we call fireChannelActive() in this case.
77                  boolean active = isActive();
78  
79                  safeSetSuccess(promise);
80                  if (!wasActive && active) {
81                      pipeline().fireChannelActive();
82                  }
83              } catch (Throwable t) {
84                  safeSetFailure(promise, annotateConnectException(t, remoteAddress));
85                  closeIfClosed();
86              }
87          }
88      }
89  
90      @Override
91      protected boolean isCompatible(EventLoop loop) {
92          return loop instanceof ThreadPerChannelEventLoop;
93      }
94  
95      /**
96       * Connect to the remote peer using the given localAddress if one is specified or {@code null} otherwise.
97       */
98      protected abstract void doConnect(
99              SocketAddress remoteAddress, SocketAddress localAddress) throws Exception;
100 
101     @Override
102     protected void doBeginRead() throws Exception {
103         if (readPending) {
104             return;
105         }
106 
107         readPending = true;
108         eventLoop().execute(readTask);
109     }
110 
111     protected abstract void doRead();
112 
113     /**
114      * @deprecated No longer supported.
115      * No longer supported.
116      */
117     @Deprecated
118     protected boolean isReadPending() {
119         return readPending;
120     }
121 
122     /**
123      * @deprecated Use {@link #clearReadPending()} if appropriate instead.
124      * No longer supported.
125      */
126     @Deprecated
127     protected void setReadPending(final boolean readPending) {
128         if (isRegistered()) {
129             EventLoop eventLoop = eventLoop();
130             if (eventLoop.inEventLoop()) {
131                 this.readPending = readPending;
132             } else {
133                 eventLoop.execute(new Runnable() {
134                     @Override
135                     public void run() {
136                         AbstractOioChannel.this.readPending = readPending;
137                     }
138                 });
139             }
140         } else {
141             this.readPending = readPending;
142         }
143     }
144 
145     /**
146      * Set read pending to {@code false}.
147      */
148     protected final void clearReadPending() {
149         if (isRegistered()) {
150             EventLoop eventLoop = eventLoop();
151             if (eventLoop.inEventLoop()) {
152                 readPending = false;
153             } else {
154                 eventLoop.execute(clearReadPendingRunnable);
155             }
156         } else {
157             // Best effort if we are not registered yet clear readPending. This happens during channel initialization.
158             readPending = false;
159         }
160     }
161 }