Mercurial Hosting > luan
annotate src/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java @ 913:17f4fe8271de
simplify connectors
| author | Franklin Schmidt <fschmidt@gmail.com> | 
|---|---|
| date | Sat, 08 Oct 2016 23:57:11 -0600 | 
| parents | 6b210bb66c63 | 
| children | 54308d65265a | 
| rev | line source | 
|---|---|
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 1 // | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 2 // ======================================================================== | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 4 // ------------------------------------------------------------------------ | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 5 // All rights reserved. This program and the accompanying materials | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 6 // are made available under the terms of the Eclipse Public License v1.0 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 7 // and Apache License v2.0 which accompanies this distribution. | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 8 // | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 9 // The Eclipse Public License is available at | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 10 // http://www.eclipse.org/legal/epl-v10.html | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 11 // | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 12 // The Apache License v2.0 is available at | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 13 // http://www.opensource.org/licenses/apache2.0.php | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 14 // | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 15 // You may elect to redistribute this code under either of these licenses. | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 16 // ======================================================================== | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 17 // | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 18 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 19 package org.eclipse.jetty.io.nio; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 20 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 21 import java.io.IOException; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 22 import java.io.InterruptedIOException; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 23 import java.nio.channels.ClosedChannelException; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 24 import java.nio.channels.SelectableChannel; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 25 import java.nio.channels.SelectionKey; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 26 import java.nio.channels.SocketChannel; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 27 import java.util.Locale; | 
| 865 | 28 import java.util.concurrent.RejectedExecutionException; | 
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 29 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 30 import org.eclipse.jetty.io.AsyncEndPoint; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 31 import org.eclipse.jetty.io.Buffer; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 32 import org.eclipse.jetty.io.ConnectedEndPoint; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 33 import org.eclipse.jetty.io.Connection; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 34 import org.eclipse.jetty.io.EofException; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 35 import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; | 
| 820 
8e9db0bbf4f9
remove org.eclipse.jetty.util.log and upgrade slf4j
 Franklin Schmidt <fschmidt@gmail.com> parents: 
802diff
changeset | 36 import org.slf4j.Logger; | 
| 
8e9db0bbf4f9
remove org.eclipse.jetty.util.log and upgrade slf4j
 Franklin Schmidt <fschmidt@gmail.com> parents: 
802diff
changeset | 37 import org.slf4j.LoggerFactory; | 
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 38 import org.eclipse.jetty.util.thread.Timeout.Task; | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 39 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 40 /* ------------------------------------------------------------ */ | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 41 /** | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 42 * An Endpoint that can be scheduled by {@link SelectorManager}. | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 43 */ | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 44 public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPoint, ConnectedEndPoint | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 45 { | 
| 865 | 46 public static final Logger LOG=LoggerFactory.getLogger("org.eclipse.jetty.io.nio"); | 
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 47 | 
| 865 | 48 private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win"); | 
| 49 private final SelectorManager.SelectSet _selectSet; | |
| 50 private final SelectorManager _manager; | |
| 51 private SelectionKey _key; | |
| 52 private final Runnable _handler = new Runnable() | |
| 53 { | |
| 54 public void run() { handle(); } | |
| 55 }; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 56 | 
| 865 | 57 /** The desired value for {@link SelectionKey#interestOps()} */ | 
| 58 private int _interestOps; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 59 | 
| 865 | 60 /** | 
| 61 * The connection instance is the handler for any IO activity on the endpoint. | |
| 62 * There is a different type of connection for HTTP, AJP, WebSocket and | |
| 63 * ProxyConnect. The connection may change for an SCEP as it is upgraded | |
| 64 * from HTTP to proxy connect or websocket. | |
| 65 */ | |
| 66 private volatile AsyncConnection _connection; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 67 | 
| 865 | 68 private static final int STATE_NEEDS_DISPATCH=-1; | 
| 69 private static final int STATE_UNDISPATCHED=0; | |
| 70 private static final int STATE_DISPATCHED=1; | |
| 71 private static final int STATE_ASYNC=2; | |
| 72 private int _state; | |
| 73 | |
| 74 private boolean _onIdle; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 75 | 
| 865 | 76 /** true if the last write operation succeed and wrote all offered bytes */ | 
| 77 private volatile boolean _writable = true; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 78 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 79 | 
| 865 | 80 /** True if a thread has is blocked in {@link #blockReadable(long)} */ | 
| 81 private boolean _readBlocked; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 82 | 
| 865 | 83 /** True if a thread has is blocked in {@link #blockWritable(long)} */ | 
| 84 private boolean _writeBlocked; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 85 | 
| 865 | 86 /** true if {@link SelectSet#destroyEndPoint(SelectChannelEndPoint)} has not been called */ | 
| 87 private boolean _open; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 88 | 
| 865 | 89 private volatile long _idleTimestamp; | 
| 90 private volatile boolean _checkIdle; | |
| 91 | |
| 92 private boolean _interruptable; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 93 | 
| 865 | 94 private boolean _ishut; | 
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 95 | 
| 865 | 96 /* ------------------------------------------------------------ */ | 
| 97 public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime) | |
| 98 throws IOException | |
| 99 { | |
| 100 super(channel, maxIdleTime); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 101 | 
| 865 | 102 _manager = selectSet.getManager(); | 
| 103 _selectSet = selectSet; | |
| 104 _state=STATE_UNDISPATCHED; | |
| 105 _onIdle=false; | |
| 106 _open=true; | |
| 107 _key = key; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 108 | 
| 865 | 109 setCheckForIdle(true); | 
| 110 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 111 | 
| 865 | 112 /* ------------------------------------------------------------ */ | 
| 113 public SelectionKey getSelectionKey() | |
| 114 { | |
| 115 synchronized (this) | |
| 116 { | |
| 117 return _key; | |
| 118 } | |
| 119 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 120 | 
| 865 | 121 /* ------------------------------------------------------------ */ | 
| 122 public SelectorManager getSelectManager() | |
| 123 { | |
| 124 return _manager; | |
| 125 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 126 | 
| 865 | 127 /* ------------------------------------------------------------ */ | 
| 128 public Connection getConnection() | |
| 129 { | |
| 130 return _connection; | |
| 131 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 132 | 
| 865 | 133 /* ------------------------------------------------------------ */ | 
| 134 public void setConnection(Connection connection) | |
| 135 { | |
| 136 Connection old=_connection; | |
| 137 _connection=(AsyncConnection)connection; | |
| 138 if (old!=null && old!=_connection) | |
| 139 _manager.endPointUpgraded(this,old); | |
| 140 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 141 | 
| 865 | 142 /* ------------------------------------------------------------ */ | 
| 143 public long getIdleTimestamp() | |
| 144 { | |
| 145 return _idleTimestamp; | |
| 146 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 147 | 
| 865 | 148 /* ------------------------------------------------------------ */ | 
| 149 /** Called by selectSet to schedule handling | |
| 150 * | |
| 151 */ | |
| 152 public void schedule() | |
| 153 { | |
| 154 synchronized (this) | |
| 155 { | |
| 156 // If there is no key, then do nothing | |
| 157 if (_key == null || !_key.isValid()) | |
| 158 { | |
| 159 _readBlocked=false; | |
| 160 _writeBlocked=false; | |
| 161 this.notifyAll(); | |
| 162 return; | |
| 163 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 164 | 
| 865 | 165 // If there are threads dispatched reading and writing | 
| 166 if (_readBlocked || _writeBlocked) | |
| 167 { | |
| 168 // assert _dispatched; | |
| 169 if (_readBlocked && _key.isReadable()) | |
| 170 _readBlocked=false; | |
| 171 if (_writeBlocked && _key.isWritable()) | |
| 172 _writeBlocked=false; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 173 | 
| 865 | 174 // wake them up is as good as a dispatched. | 
| 175 this.notifyAll(); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 176 | 
| 865 | 177 // we are not interested in further selecting | 
| 178 _key.interestOps(0); | |
| 179 if (_state<STATE_DISPATCHED) | |
| 180 updateKey(); | |
| 181 return; | |
| 182 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 183 | 
| 865 | 184 // Remove writeable op | 
| 185 if ((_key.readyOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && (_key.interestOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) | |
| 186 { | |
| 187 // Remove writeable op | |
| 188 _interestOps = _key.interestOps() & ~SelectionKey.OP_WRITE; | |
| 189 _key.interestOps(_interestOps); | |
| 190 _writable = true; // Once writable is in ops, only removed with dispatch. | |
| 191 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 192 | 
| 865 | 193 // If dispatched, then deregister interest | 
| 194 if (_state>=STATE_DISPATCHED) | |
| 195 _key.interestOps(0); | |
| 196 else | |
| 197 { | |
| 198 // other wise do the dispatch | |
| 199 dispatch(); | |
| 200 if (_state>=STATE_DISPATCHED && !_selectSet.getManager().isDeferringInterestedOps0()) | |
| 201 { | |
| 202 _key.interestOps(0); | |
| 203 } | |
| 204 } | |
| 205 } | |
| 206 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 207 | 
| 865 | 208 /* ------------------------------------------------------------ */ | 
| 209 public void asyncDispatch() | |
| 210 { | |
| 211 synchronized(this) | |
| 212 { | |
| 213 switch(_state) | |
| 214 { | |
| 215 case STATE_NEEDS_DISPATCH: | |
| 216 case STATE_UNDISPATCHED: | |
| 217 dispatch(); | |
| 218 break; | |
| 219 | |
| 220 case STATE_DISPATCHED: | |
| 221 case STATE_ASYNC: | |
| 222 _state=STATE_ASYNC; | |
| 223 break; | |
| 224 } | |
| 225 } | |
| 226 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 227 | 
| 865 | 228 /* ------------------------------------------------------------ */ | 
| 229 public void dispatch() | |
| 230 { | |
| 231 synchronized(this) | |
| 232 { | |
| 233 if (_state<=STATE_UNDISPATCHED) | |
| 234 { | |
| 235 if (_onIdle) | |
| 236 _state = STATE_NEEDS_DISPATCH; | |
| 237 else | |
| 238 { | |
| 239 _state = STATE_DISPATCHED; | |
| 240 try { | |
| 241 _manager.execute(_handler); | |
| 242 } catch(RejectedExecutionException e) { | |
| 243 _state = STATE_NEEDS_DISPATCH; | |
| 244 LOG.warn("Dispatched Failed! "+this+" to "+_manager); | |
| 245 updateKey(); | |
| 246 } | |
| 247 } | |
| 248 } | |
| 249 } | |
| 250 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 251 | 
| 865 | 252 /* ------------------------------------------------------------ */ | 
| 253 /** | |
| 254 * Called when a dispatched thread is no longer handling the endpoint. | |
| 255 * The selection key operations are updated. | |
| 256 * @return If false is returned, the endpoint has been redispatched and | |
| 257 * thread must keep handling the endpoint. | |
| 258 */ | |
| 259 protected boolean undispatch() | |
| 260 { | |
| 261 synchronized (this) | |
| 262 { | |
| 263 switch(_state) | |
| 264 { | |
| 265 case STATE_ASYNC: | |
| 266 _state=STATE_DISPATCHED; | |
| 267 return false; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 268 | 
| 865 | 269 default: | 
| 270 _state=STATE_UNDISPATCHED; | |
| 271 updateKey(); | |
| 272 return true; | |
| 273 } | |
| 274 } | |
| 275 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 276 | 
| 865 | 277 /* ------------------------------------------------------------ */ | 
| 278 public void cancelTimeout(Task task) | |
| 279 { | |
| 280 getSelectSet().cancelTimeout(task); | |
| 281 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 282 | 
| 865 | 283 /* ------------------------------------------------------------ */ | 
| 284 public void scheduleTimeout(Task task, long timeoutMs) | |
| 285 { | |
| 286 getSelectSet().scheduleTimeout(task,timeoutMs); | |
| 287 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 288 | 
| 865 | 289 /* ------------------------------------------------------------ */ | 
| 290 public void setCheckForIdle(boolean check) | |
| 291 { | |
| 292 if (check) | |
| 293 { | |
| 294 _idleTimestamp=System.currentTimeMillis(); | |
| 295 _checkIdle=true; | |
| 296 } | |
| 297 else | |
| 298 _checkIdle=false; | |
| 299 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 300 | 
| 865 | 301 /* ------------------------------------------------------------ */ | 
| 302 public boolean isCheckForIdle() | |
| 303 { | |
| 304 return _checkIdle; | |
| 305 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 306 | 
| 865 | 307 /* ------------------------------------------------------------ */ | 
| 308 protected void notIdle() | |
| 309 { | |
| 310 _idleTimestamp=System.currentTimeMillis(); | |
| 311 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 312 | 
| 865 | 313 /* ------------------------------------------------------------ */ | 
| 314 public void checkIdleTimestamp(long now) | |
| 315 { | |
| 316 if (isCheckForIdle() && _maxIdleTime>0) | |
| 317 { | |
| 318 final long idleForMs=now-_idleTimestamp; | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 319 | 
| 865 | 320 if (idleForMs>_maxIdleTime) | 
| 321 { | |
| 322 // Don't idle out again until onIdleExpired task completes. | |
| 323 setCheckForIdle(false); | |
| 324 _manager.execute(new Runnable() | |
| 325 { | |
| 326 public void run() | |
| 327 { | |
| 328 try | |
| 329 { | |
| 330 onIdleExpired(idleForMs); | |
| 331 } | |
| 332 finally | |
| 333 { | |
| 334 setCheckForIdle(true); | |
| 335 } | |
| 336 } | |
| 337 }); | |
| 338 } | |
| 339 } | |
| 340 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 341 | 
| 865 | 342 /* ------------------------------------------------------------ */ | 
| 343 public void onIdleExpired(long idleForMs) | |
| 344 { | |
| 345 try | |
| 346 { | |
| 347 synchronized (this) | |
| 348 { | |
| 349 _onIdle=true; | |
| 350 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 351 | 
| 865 | 352 _connection.onIdleExpired(idleForMs); | 
| 353 } | |
| 354 finally | |
| 355 { | |
| 356 synchronized (this) | |
| 357 { | |
| 358 _onIdle=false; | |
| 359 if (_state==STATE_NEEDS_DISPATCH) | |
| 360 dispatch(); | |
| 361 } | |
| 362 } | |
| 363 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 364 | 
| 865 | 365 /* ------------------------------------------------------------ */ | 
| 366 @Override | |
| 367 public int fill(Buffer buffer) throws IOException | |
| 368 { | |
| 369 int fill=super.fill(buffer); | |
| 370 if (fill>0) | |
| 371 notIdle(); | |
| 372 return fill; | |
| 373 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 374 | 
| 865 | 375 /* ------------------------------------------------------------ */ | 
| 376 @Override | |
| 377 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException | |
| 378 { | |
| 379 int l = super.flush(header, buffer, trailer); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 380 | 
| 865 | 381 // If there was something to write and it wasn't written, then we are not writable. | 
| 382 if (l==0 && ( header!=null && header.hasContent() || buffer!=null && buffer.hasContent() || trailer!=null && trailer.hasContent())) | |
| 383 { | |
| 384 synchronized (this) | |
| 385 { | |
| 386 _writable=false; | |
| 387 if (_state<STATE_DISPATCHED) | |
| 388 updateKey(); | |
| 389 } | |
| 390 } | |
| 391 else if (l>0) | |
| 392 { | |
| 393 _writable=true; | |
| 394 notIdle(); | |
| 395 } | |
| 396 return l; | |
| 397 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 398 | 
| 865 | 399 /* ------------------------------------------------------------ */ | 
| 400 /* | |
| 401 */ | |
| 402 @Override | |
| 403 public int flush(Buffer buffer) throws IOException | |
| 404 { | |
| 405 int l = super.flush(buffer); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 406 | 
| 865 | 407 // If there was something to write and it wasn't written, then we are not writable. | 
| 408 if (l==0 && buffer!=null && buffer.hasContent()) | |
| 409 { | |
| 410 synchronized (this) | |
| 411 { | |
| 412 _writable=false; | |
| 413 if (_state<STATE_DISPATCHED) | |
| 414 updateKey(); | |
| 415 } | |
| 416 } | |
| 417 else if (l>0) | |
| 418 { | |
| 419 _writable=true; | |
| 420 notIdle(); | |
| 421 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 422 | 
| 865 | 423 return l; | 
| 424 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 425 | 
| 865 | 426 /* ------------------------------------------------------------ */ | 
| 427 /* | |
| 428 * Allows thread to block waiting for further events. | |
| 429 */ | |
| 430 @Override | |
| 431 public boolean blockReadable(long timeoutMs) throws IOException | |
| 432 { | |
| 433 synchronized (this) | |
| 434 { | |
| 435 if (isInputShutdown()) | |
| 436 throw new EofException(); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 437 | 
| 865 | 438 long now=_selectSet.getNow(); | 
| 439 long end=now+timeoutMs; | |
| 440 boolean check=isCheckForIdle(); | |
| 441 setCheckForIdle(true); | |
| 442 try | |
| 443 { | |
| 444 _readBlocked=true; | |
| 445 while (!isInputShutdown() && _readBlocked) | |
| 446 { | |
| 447 try | |
| 448 { | |
| 449 updateKey(); | |
| 450 this.wait(timeoutMs>0?(end-now):10000); | |
| 451 } | |
| 452 catch (final InterruptedException e) | |
| 453 { | |
| 454 LOG.warn("",e); | |
| 455 if (_interruptable) | |
| 456 throw new InterruptedIOException(){{this.initCause(e);}}; | |
| 457 } | |
| 458 finally | |
| 459 { | |
| 460 now=_selectSet.getNow(); | |
| 461 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 462 | 
| 865 | 463 if (_readBlocked && timeoutMs>0 && now>=end) | 
| 464 return false; | |
| 465 } | |
| 466 } | |
| 467 finally | |
| 468 { | |
| 469 _readBlocked=false; | |
| 470 setCheckForIdle(check); | |
| 471 } | |
| 472 } | |
| 473 return true; | |
| 474 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 475 | 
| 865 | 476 /* ------------------------------------------------------------ */ | 
| 477 /* | |
| 478 * Allows thread to block waiting for further events. | |
| 479 */ | |
| 480 @Override | |
| 481 public boolean blockWritable(long timeoutMs) throws IOException | |
| 482 { | |
| 483 synchronized (this) | |
| 484 { | |
| 485 if (isOutputShutdown()) | |
| 486 throw new EofException(); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 487 | 
| 865 | 488 long now=_selectSet.getNow(); | 
| 489 long end=now+timeoutMs; | |
| 490 boolean check=isCheckForIdle(); | |
| 491 setCheckForIdle(true); | |
| 492 try | |
| 493 { | |
| 494 _writeBlocked=true; | |
| 495 while (_writeBlocked && !isOutputShutdown()) | |
| 496 { | |
| 497 try | |
| 498 { | |
| 499 updateKey(); | |
| 500 this.wait(timeoutMs>0?(end-now):10000); | |
| 501 } | |
| 502 catch (final InterruptedException e) | |
| 503 { | |
| 504 LOG.warn("",e); | |
| 505 if (_interruptable) | |
| 506 throw new InterruptedIOException(){{this.initCause(e);}}; | |
| 507 } | |
| 508 finally | |
| 509 { | |
| 510 now=_selectSet.getNow(); | |
| 511 } | |
| 512 if (_writeBlocked && timeoutMs>0 && now>=end) | |
| 513 return false; | |
| 514 } | |
| 515 } | |
| 516 finally | |
| 517 { | |
| 518 _writeBlocked=false; | |
| 519 setCheckForIdle(check); | |
| 520 } | |
| 521 } | |
| 522 return true; | |
| 523 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 524 | 
| 865 | 525 /* ------------------------------------------------------------ */ | 
| 526 /** Set the interruptable mode of the endpoint. | |
| 527 * If set to false (default), then interrupts are assumed to be spurious | |
| 528 * and blocking operations continue unless the endpoint has been closed. | |
| 529 * If true, then interrupts of blocking operations result in InterruptedIOExceptions | |
| 530 * being thrown. | |
| 531 * @param interupable | |
| 532 */ | |
| 533 public void setInterruptable(boolean interupable) | |
| 534 { | |
| 535 synchronized (this) | |
| 536 { | |
| 537 _interruptable=interupable; | |
| 538 } | |
| 539 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 540 | 
| 865 | 541 /* ------------------------------------------------------------ */ | 
| 542 public boolean isInterruptable() | |
| 543 { | |
| 544 return _interruptable; | |
| 545 } | |
| 546 | |
| 547 /* ------------------------------------------------------------ */ | |
| 548 /** | |
| 549 * @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite() | |
| 550 */ | |
| 551 public void scheduleWrite() | |
| 552 { | |
| 553 if (_writable) | |
| 554 LOG.debug("Required scheduleWrite {}",this); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 555 | 
| 865 | 556 _writable=false; | 
| 557 updateKey(); | |
| 558 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 559 | 
| 865 | 560 /* ------------------------------------------------------------ */ | 
| 561 public boolean isWritable() | |
| 562 { | |
| 563 return _writable; | |
| 564 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 565 | 
| 865 | 566 /* ------------------------------------------------------------ */ | 
| 567 public boolean hasProgressed() | |
| 568 { | |
| 569 return false; | |
| 570 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 571 | 
| 865 | 572 /* ------------------------------------------------------------ */ | 
| 573 /** | |
| 574 * Updates selection key. Adds operations types to the selection key as needed. No operations | |
| 575 * are removed as this is only done during dispatch. This method records the new key and | |
| 576 * schedules a call to doUpdateKey to do the keyChange | |
| 577 */ | |
| 578 private void updateKey() | |
| 579 { | |
| 580 final boolean changed; | |
| 581 synchronized (this) | |
| 582 { | |
| 583 int current_ops=-1; | |
| 584 if (getChannel().isOpen()) | |
| 585 { | |
| 586 boolean read_interest = _readBlocked || (_state<STATE_DISPATCHED && !_connection.isSuspended()); | |
| 587 boolean write_interest= _writeBlocked || (_state<STATE_DISPATCHED && !_writable); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 588 | 
| 865 | 589 _interestOps = | 
| 590 ((!_socket.isInputShutdown() && read_interest ) ? SelectionKey.OP_READ : 0) | |
| 591 | ((!_socket.isOutputShutdown()&& write_interest) ? SelectionKey.OP_WRITE : 0); | |
| 592 try | |
| 593 { | |
| 594 current_ops = ((_key!=null && _key.isValid())?_key.interestOps():-1); | |
| 595 } | |
| 596 catch(Exception e) | |
| 597 { | |
| 598 _key=null; | |
| 599 LOG.trace("",e); | |
| 600 } | |
| 601 } | |
| 602 changed=_interestOps!=current_ops; | |
| 603 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 604 | 
| 865 | 605 if(changed) | 
| 606 { | |
| 607 _selectSet.addChange(this); | |
| 608 _selectSet.wakeup(); | |
| 609 } | |
| 610 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 611 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 612 | 
| 865 | 613 /* ------------------------------------------------------------ */ | 
| 614 /** | |
| 615 * Synchronize the interestOps with the actual key. Call is scheduled by a call to updateKey | |
| 616 */ | |
| 617 void doUpdateKey() | |
| 618 { | |
| 619 synchronized (this) | |
| 620 { | |
| 621 if (getChannel().isOpen()) | |
| 622 { | |
| 623 if (_interestOps>0) | |
| 624 { | |
| 625 if (_key==null || !_key.isValid()) | |
| 626 { | |
| 627 SelectableChannel sc = (SelectableChannel)getChannel(); | |
| 628 if (sc.isRegistered()) | |
| 629 { | |
| 630 updateKey(); | |
| 631 } | |
| 632 else | |
| 633 { | |
| 634 try | |
| 635 { | |
| 636 _key=((SelectableChannel)getChannel()).register(_selectSet.getSelector(),_interestOps,this); | |
| 637 } | |
| 638 catch (Exception e) | |
| 639 { | |
| 640 LOG.trace("",e); | |
| 641 if (_key!=null && _key.isValid()) | |
| 642 { | |
| 643 _key.cancel(); | |
| 644 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 645 | 
| 865 | 646 if (_open) | 
| 647 { | |
| 648 _selectSet.destroyEndPoint(this); | |
| 649 } | |
| 650 _open=false; | |
| 651 _key = null; | |
| 652 } | |
| 653 } | |
| 654 } | |
| 655 else | |
| 656 { | |
| 657 _key.interestOps(_interestOps); | |
| 658 } | |
| 659 } | |
| 660 else | |
| 661 { | |
| 662 if (_key!=null && _key.isValid()) | |
| 663 _key.interestOps(0); | |
| 664 else | |
| 665 _key=null; | |
| 666 } | |
| 667 } | |
| 668 else | |
| 669 { | |
| 670 if (_key!=null && _key.isValid()) | |
| 671 _key.cancel(); | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 672 | 
| 865 | 673 if (_open) | 
| 674 { | |
| 675 _open=false; | |
| 676 _selectSet.destroyEndPoint(this); | |
| 677 } | |
| 678 _key = null; | |
| 679 } | |
| 680 } | |
| 681 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 682 | 
| 865 | 683 /* ------------------------------------------------------------ */ | 
| 684 /* | |
| 685 */ | |
| 686 protected void handle() | |
| 687 { | |
| 688 boolean dispatched=true; | |
| 689 try | |
| 690 { | |
| 691 while(dispatched) | |
| 692 { | |
| 693 try | |
| 694 { | |
| 695 while(true) | |
| 696 { | |
| 697 final AsyncConnection next = (AsyncConnection)_connection.handle(); | |
| 698 if (next!=_connection) | |
| 699 { | |
| 700 LOG.debug("{} replaced {}",next,_connection); | |
| 701 Connection old=_connection; | |
| 702 _connection=next; | |
| 703 _manager.endPointUpgraded(this,old); | |
| 704 continue; | |
| 705 } | |
| 706 break; | |
| 707 } | |
| 708 } | |
| 709 catch (ClosedChannelException e) | |
| 710 { | |
| 711 LOG.trace("",e); | |
| 712 } | |
| 713 catch (EofException e) | |
| 714 { | |
| 715 LOG.debug("EOF", e); | |
| 716 try{close();} | |
| 717 catch(IOException e2){LOG.trace("",e2);} | |
| 718 } | |
| 719 catch (IOException e) | |
| 720 { | |
| 721 LOG.warn(e.toString()); | |
| 722 try{close();} | |
| 723 catch(IOException e2){LOG.trace("",e2);} | |
| 724 } | |
| 725 catch (Throwable e) | |
| 726 { | |
| 727 LOG.warn("handle failed", e); | |
| 728 try{close();} | |
| 729 catch(IOException e2){LOG.trace("",e2);} | |
| 730 } | |
| 731 finally | |
| 732 { | |
| 733 if (!_ishut && isInputShutdown() && isOpen()) | |
| 734 { | |
| 735 _ishut=true; | |
| 736 try | |
| 737 { | |
| 738 _connection.onInputShutdown(); | |
| 739 } | |
| 740 catch(Throwable x) | |
| 741 { | |
| 742 LOG.warn("onInputShutdown failed", x); | |
| 743 try{close();} | |
| 744 catch(IOException e2){LOG.trace("",e2);} | |
| 745 } | |
| 746 finally | |
| 747 { | |
| 748 updateKey(); | |
| 749 } | |
| 750 } | |
| 751 dispatched=!undispatch(); | |
| 752 } | |
| 753 } | |
| 754 } | |
| 755 finally | |
| 756 { | |
| 757 if (dispatched) | |
| 758 { | |
| 759 dispatched=!undispatch(); | |
| 760 while (dispatched) | |
| 761 { | |
| 762 LOG.warn("SCEP.run() finally DISPATCHED"); | |
| 763 dispatched=!undispatch(); | |
| 764 } | |
| 765 } | |
| 766 } | |
| 767 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 768 | 
| 865 | 769 /* ------------------------------------------------------------ */ | 
| 770 /* | |
| 771 * @see org.eclipse.io.nio.ChannelEndPoint#close() | |
| 772 */ | |
| 773 @Override | |
| 774 public void close() throws IOException | |
| 775 { | |
| 776 // On unix systems there is a JVM issue that if you cancel before closing, it can | |
| 777 // cause the selector to block waiting for a channel to close and that channel can | |
| 778 // block waiting for the remote end. But on windows, if you don't cancel before a | |
| 779 // close, then the selector can block anyway! | |
| 780 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318 | |
| 781 if (WORK_AROUND_JVM_BUG_6346658) | |
| 782 { | |
| 783 try | |
| 784 { | |
| 785 SelectionKey key = _key; | |
| 786 if (key!=null) | |
| 787 key.cancel(); | |
| 788 } | |
| 789 catch (Throwable e) | |
| 790 { | |
| 791 LOG.trace("",e); | |
| 792 } | |
| 793 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 794 | 
| 865 | 795 try | 
| 796 { | |
| 797 super.close(); | |
| 798 } | |
| 799 catch (IOException e) | |
| 800 { | |
| 801 LOG.trace("",e); | |
| 802 } | |
| 803 finally | |
| 804 { | |
| 805 updateKey(); | |
| 806 } | |
| 807 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 808 | 
| 865 | 809 /* ------------------------------------------------------------ */ | 
| 810 @Override | |
| 811 public String toString() | |
| 812 { | |
| 813 // Do NOT use synchronized (this) | |
| 814 // because it's very easy to deadlock when debugging is enabled. | |
| 815 // We do a best effort to print the right toString() and that's it. | |
| 816 SelectionKey key = _key; | |
| 817 String keyString = ""; | |
| 818 if (key != null) | |
| 819 { | |
| 820 if (key.isValid()) | |
| 821 { | |
| 822 if (key.isReadable()) | |
| 823 keyString += "r"; | |
| 824 if (key.isWritable()) | |
| 825 keyString += "w"; | |
| 826 } | |
| 827 else | |
| 828 { | |
| 829 keyString += "!"; | |
| 830 } | |
| 831 } | |
| 832 else | |
| 833 { | |
| 834 keyString += "-"; | |
| 835 } | |
| 836 return String.format("SCEP@%x{l(%s)<->r(%s),s=%d,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}", | |
| 837 hashCode(), | |
| 838 _socket.getRemoteSocketAddress(), | |
| 839 _socket.getLocalSocketAddress(), | |
| 840 _state, | |
| 841 isOpen(), | |
| 842 isInputShutdown(), | |
| 843 isOutputShutdown(), | |
| 844 _readBlocked, | |
| 845 _writeBlocked, | |
| 846 _writable, | |
| 847 _interestOps, | |
| 848 keyString, | |
| 849 _connection); | |
| 850 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 851 | 
| 865 | 852 /* ------------------------------------------------------------ */ | 
| 853 public SelectSet getSelectSet() | |
| 854 { | |
| 855 return _selectSet; | |
| 856 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 857 | 
| 865 | 858 /* ------------------------------------------------------------ */ | 
| 859 /** | |
| 860 * Don't set the SoTimeout | |
| 861 * @see org.eclipse.jetty.io.nio.ChannelEndPoint#setMaxIdleTime(int) | |
| 862 */ | |
| 863 @Override | |
| 864 public void setMaxIdleTime(int timeMs) throws IOException | |
| 865 { | |
| 866 _maxIdleTime=timeMs; | |
| 867 } | |
| 802 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 868 | 
| 
3428c60d7cfc
replace jetty jars with source
 Franklin Schmidt <fschmidt@gmail.com> parents: diff
changeset | 869 } | 
