| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| Context |
|
| 0.0;0 | ||||
| Context$1 |
|
| 0.0;0 | ||||
| Context$AsyncQueueReadableContextWrapper |
|
| 0.0;0 | ||||
| Context$AsyncQueueWritableContextWrapper |
|
| 0.0;0 | ||||
| Context$AttributeScope |
|
| 0.0;0 | ||||
| Context$KeyRegistrationState |
|
| 0.0;0 | ||||
| Context$OpType |
|
| 0.0;0 |
| 1 | /* | |
| 2 | * | |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
| 4 | * | |
| 5 | * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved. | |
| 6 | * | |
| 7 | * The contents of this file are subject to the terms of either the GNU | |
| 8 | * General Public License Version 2 only ("GPL") or the Common Development | |
| 9 | * and Distribution License("CDDL") (collectively, the "License"). You | |
| 10 | * may not use this file except in compliance with the License. You can obtain | |
| 11 | * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html | |
| 12 | * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific | |
| 13 | * language governing permissions and limitations under the License. | |
| 14 | * | |
| 15 | * When distributing the software, include this License Header Notice in each | |
| 16 | * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. | |
| 17 | * Sun designates this particular file as subject to the "Classpath" exception | |
| 18 | * as provided by Sun in the GPL Version 2 section of the License file that | |
| 19 | * accompanied this code. If applicable, add the following below the License | |
| 20 | * Header, with the fields enclosed by brackets [] replaced by your own | |
| 21 | * identifying information: "Portions Copyrighted [year] | |
| 22 | * [name of copyright owner]" | |
| 23 | * | |
| 24 | * Contributor(s): | |
| 25 | * | |
| 26 | * If you wish your version of this file to be governed by only the CDDL or | |
| 27 | * only the GPL Version 2, indicate your decision by adding "[Contributor] | |
| 28 | * elects to include this software in this distribution under the [CDDL or GPL | |
| 29 | * Version 2] license." If you don't indicate a single choice of license, a | |
| 30 | * recipient has the option to distribute your version of this file under | |
| 31 | * either the CDDL, the GPL Version 2 or to extend the choice of license to | |
| 32 | * its licensees as provided above. However, if you add GPL Version 2 code | |
| 33 | * and therefore, elected the GPL Version 2 license, then the option applies | |
| 34 | * only if the new code is made subject to such option by the copyright | |
| 35 | * holder. | |
| 36 | * | |
| 37 | */ | |
| 38 | ||
| 39 | package com.sun.grizzly; | |
| 40 | ||
| 41 | import com.sun.grizzly.async.AsyncQueueDataProcessor; | |
| 42 | import com.sun.grizzly.async.AsyncQueueReadable; | |
| 43 | import com.sun.grizzly.async.AsyncQueueReader; | |
| 44 | import com.sun.grizzly.async.AsyncQueueWritable; | |
| 45 | import com.sun.grizzly.async.AsyncQueueWriter; | |
| 46 | import com.sun.grizzly.async.AsyncReadCallbackHandler; | |
| 47 | import com.sun.grizzly.async.AsyncReadCondition; | |
| 48 | import com.sun.grizzly.async.AsyncWriteCallbackHandler; | |
| 49 | import com.sun.grizzly.util.AttributeHolder; | |
| 50 | import com.sun.grizzly.util.Copyable; | |
| 51 | import com.sun.grizzly.util.SelectionKeyAttachment; | |
| 52 | import com.sun.grizzly.util.WorkerThread; | |
| 53 | import java.io.IOException; | |
| 54 | import java.net.SocketAddress; | |
| 55 | import java.nio.ByteBuffer; | |
| 56 | import java.nio.channels.SelectionKey; | |
| 57 | import java.util.HashMap; | |
| 58 | import java.util.Map; | |
| 59 | import java.util.concurrent.atomic.AtomicInteger; | |
| 60 | import java.util.logging.Level; | |
| 61 | ||
| 62 | /** | |
| 63 | * This Object is used to share information between the Grizzly Framework | |
| 64 | * classes and {@link ProtocolFilter} implementation. Since {@link Context} | |
| 65 | * is a pooled resource | |
| 66 | * {@link Controller#pollContext(java.nio.channels.SelectionKey)} | |
| 67 | * transactions using {@link Context} outside its {@link ProtocolChain} | |
| 68 | * must invoke {@link #incrementRefCount()} and | |
| 69 | * {@link Controller#returnContext(com.sun.grizzly.Context)} to keep its pooling | |
| 70 | * intact. | |
| 71 | * @author Jeanfrancois Arcand | |
| 72 | */ | |
| 73 | 173324 | public class Context implements AttributeHolder, Copyable { |
| 74 | ||
| 75 | ||
| 76 | 6 | public enum AttributeScope { |
| 77 | 1 | REQUEST, |
| 78 | 1 | CONNECTION, |
| 79 | 1 | SELECTOR, |
| 80 | 1 | CONTROLLER |
| 81 | } | |
| 82 | ||
| 83 | /** | |
| 84 | * A {@link SelectionKey}'s registration state. | |
| 85 | */ | |
| 86 | 4 | public enum KeyRegistrationState { |
| 87 | /** A cancelled {@link SelectionKey} registration state. */ | |
| 88 | 1 | CANCEL, |
| 89 | /** A registered {@link SelectionKey} registration state. */ | |
| 90 | 1 | REGISTER, |
| 91 | /** A {@link SelectionKey} with no registration state. */ | |
| 92 | 1 | NONE } |
| 93 | ||
| 94 | ||
| 95 | /** | |
| 96 | * The list of possible {@link SelectionKey}.OP_XXXX. | |
| 97 | */ | |
| 98 | 7 | public enum OpType { OP_READ, |
| 99 | 1 | OP_WRITE, |
| 100 | 1 | OP_CONNECT, |
| 101 | 1 | OP_READ_WRITE, |
| 102 | 1 | OP_ACCEPT |
| 103 | } | |
| 104 | ||
| 105 | ||
| 106 | /** | |
| 107 | * The current {@link SelectionKey} interest ops this Context is processing. | |
| 108 | */ | |
| 109 | private OpType currentOpType; | |
| 110 | ||
| 111 | ||
| 112 | /** | |
| 113 | * The {@link ProtocolChain} used to execute this {@link Context} | |
| 114 | */ | |
| 115 | private ProtocolChain protocolChain; | |
| 116 | ||
| 117 | ||
| 118 | /** | |
| 119 | * Constant 'throwable' String | |
| 120 | */ | |
| 121 | public final static String THROWABLE ="throwable"; | |
| 122 | ||
| 123 | ||
| 124 | /** | |
| 125 | * Used to share object between {@link ProtocolFilter}. | |
| 126 | * WARNING: Attributes which are added are never removed automatically | |
| 127 | * The removal operation must be done explicitly inside a {@link ProtocolFilter}. | |
| 128 | */ | |
| 129 | 261 | private Map<String,Object> attributes = null; |
| 130 | ||
| 131 | ||
| 132 | /** | |
| 133 | * The current connection (@link SelectionKey}. | |
| 134 | */ | |
| 135 | private SelectionKey key; | |
| 136 | ||
| 137 | ||
| 138 | /** | |
| 139 | * The {@link SelectorHandler} associated with this Context. | |
| 140 | */ | |
| 141 | private SelectorHandler selectorHandler; | |
| 142 | ||
| 143 | ||
| 144 | /** | |
| 145 | * The {@link Controller} associated with this Context. | |
| 146 | */ | |
| 147 | private Controller controller; | |
| 148 | ||
| 149 | ||
| 150 | /** | |
| 151 | * The state's of the key registration. | |
| 152 | */ | |
| 153 | 261 | private KeyRegistrationState keyRegistrationState |
| 154 | = KeyRegistrationState.REGISTER; | |
| 155 | ||
| 156 | ||
| 157 | /** | |
| 158 | * The current {@linl Pipeline} that execute this object. | |
| 159 | */ | |
| 160 | private Pipeline pipeline; | |
| 161 | ||
| 162 | ||
| 163 | /** | |
| 164 | * An optional {@link IOEvent} that can be invoked | |
| 165 | * before the {@link ProtocolChain} is invoked. | |
| 166 | */ | |
| 167 | private IOEvent<Context> ioEvent; | |
| 168 | ||
| 169 | ||
| 170 | /** | |
| 171 | * {@link AsyncQueueReader} | |
| 172 | */ | |
| 173 | private AsyncQueueReader asyncQueueReader; | |
| 174 | ||
| 175 | /** | |
| 176 | * {@link AsyncQueueWriter} | |
| 177 | */ | |
| 178 | private AsyncQueueWriter asyncQueueWriter; | |
| 179 | ||
| 180 | /** | |
| 181 | * {@link AsyncQueueReadable} | |
| 182 | */ | |
| 183 | private AsyncQueueReadable asyncQueueReadable; | |
| 184 | ||
| 185 | /** | |
| 186 | * {@link AsyncQueueWritable} | |
| 187 | */ | |
| 188 | private AsyncQueueWritable asyncQueueWritable; | |
| 189 | ||
| 190 | ||
| 191 | /** | |
| 192 | * Is this context suspended. | |
| 193 | */ | |
| 194 | 261 | private boolean isSuspended = false; |
| 195 | ||
| 196 | /** | |
| 197 | * Reference Counter indicating how many Threads share this Context. | |
| 198 | * Starts at one already counting {@link WorkerThread}. | |
| 199 | */ | |
| 200 | 261 | private AtomicInteger refCounter=new AtomicInteger(1); |
| 201 | ||
| 202 | ||
| 203 | /** | |
| 204 | * Constructor | |
| 205 | */ | |
| 206 | 261 | public Context() { |
| 207 | 261 | } |
| 208 | ||
| 209 | ||
| 210 | public void copyTo(Copyable copy) { | |
| 211 | 0 | Context copyContext = (Context) copy; |
| 212 | 0 | copyContext.currentOpType = currentOpType; |
| 213 | 0 | copyContext.protocolChain = protocolChain; |
| 214 | 0 | if (attributes != null) { |
| 215 | 0 | copyContext.attributes = new HashMap<String, Object>(attributes); |
| 216 | } | |
| 217 | 0 | copyContext.key = key; |
| 218 | 0 | copyContext.selectorHandler = selectorHandler; |
| 219 | 0 | copyContext.controller = controller; |
| 220 | 0 | copyContext.keyRegistrationState = keyRegistrationState; |
| 221 | 0 | copyContext.pipeline = pipeline; |
| 222 | 0 | copyContext.ioEvent = ioEvent; |
| 223 | 0 | copyContext.asyncQueueReader = asyncQueueReader; |
| 224 | 0 | copyContext.asyncQueueWriter = asyncQueueWriter; |
| 225 | 0 | } |
| 226 | ||
| 227 | /** | |
| 228 | * Remove a key/value object. | |
| 229 | * @param key - name of an attribute | |
| 230 | * @return attribute which has been removed | |
| 231 | */ | |
| 232 | public Object removeAttribute(String key){ | |
| 233 | 165998 | if (attributes == null){ |
| 234 | 56606 | return null; |
| 235 | } | |
| 236 | 109392 | return attributes.remove(key); |
| 237 | } | |
| 238 | ||
| 239 | ||
| 240 | /** | |
| 241 | * Set a key/value object. | |
| 242 | * @param key - name of an attribute | |
| 243 | * @param value - value of named attribute | |
| 244 | */ | |
| 245 | public void setAttribute(String key,Object value){ | |
| 246 | 21124 | if (attributes == null){ |
| 247 | 41 | attributes = new HashMap<String,Object>(); |
| 248 | } | |
| 249 | 21124 | attributes.put(key,value); |
| 250 | 21124 | } |
| 251 | ||
| 252 | ||
| 253 | /** | |
| 254 | * Return an object based on a key. | |
| 255 | * @param key - name of an attribute | |
| 256 | * @return - attribute value for the <tt>key</tt>, null if <tt>key</tt> | |
| 257 | * does not exist in <tt>attributes</tt> | |
| 258 | */ | |
| 259 | public Object getAttribute(String key){ | |
| 260 | 21006 | if (attributes == null){ |
| 261 | 1 | return null; |
| 262 | } | |
| 263 | 21005 | return attributes.get(key); |
| 264 | } | |
| 265 | ||
| 266 | ||
| 267 | /** | |
| 268 | * Return {@link AttributeHolder}, which corresponds to the | |
| 269 | * given {@link AttributeScope}> | |
| 270 | * | |
| 271 | * @param scope - {@link AttributeScope}> | |
| 272 | * @return - {@link AttributeHolder} instance, which contains | |
| 273 | * {@link AttributeScope}> attributes | |
| 274 | */ | |
| 275 | public AttributeHolder getAttributeHolderByScope(AttributeScope scope){ | |
| 276 | 52743 | AttributeHolder holder = null; |
| 277 | 1 | switch(scope) { |
| 278 | case REQUEST: | |
| 279 | 0 | holder = this; |
| 280 | 0 | break; |
| 281 | case CONNECTION: | |
| 282 | 52743 | Object attachment = getSelectionKey().attachment(); |
| 283 | 52743 | if (attachment instanceof AttributeHolder) { |
| 284 | 52742 | holder = (AttributeHolder) attachment; |
| 285 | } | |
| 286 | break; | |
| 287 | case SELECTOR: | |
| 288 | 0 | holder = selectorHandler; |
| 289 | 0 | break; |
| 290 | case CONTROLLER: | |
| 291 | 0 | holder = controller; |
| 292 | break; | |
| 293 | } | |
| 294 | ||
| 295 | 52743 | return holder; |
| 296 | } | |
| 297 | ||
| 298 | ||
| 299 | /** | |
| 300 | * Set a {@link Map} of attribute name/value pairs. | |
| 301 | * Old {@link AttributeHolder} values will not be available. | |
| 302 | * Later changes of this {@link Map} will lead to changes to the current | |
| 303 | * {@link AttributeHolder}. | |
| 304 | * | |
| 305 | * @param attributes - map of name/value pairs | |
| 306 | */ | |
| 307 | public void setAttributes(Map<String, Object> attributes) { | |
| 308 | 0 | this.attributes = attributes; |
| 309 | 0 | } |
| 310 | ||
| 311 | ||
| 312 | /** | |
| 313 | * Return a {@link Map} of attribute name/value pairs. | |
| 314 | * Updates, performed on the returned {@link Map} will be reflected in | |
| 315 | * this {@link AttributeHolder} | |
| 316 | * | |
| 317 | * @return - {@link Map} of attribute name/value pairs | |
| 318 | */ | |
| 319 | public Map<String, Object> getAttributes() { | |
| 320 | 0 | return attributes; |
| 321 | } | |
| 322 | ||
| 323 | ||
| 324 | /** | |
| 325 | * Return the current {@link SelectionKey}. | |
| 326 | * @return - this Context's SelectionKey | |
| 327 | */ | |
| 328 | public SelectionKey getSelectionKey() { | |
| 329 | 619960 | return key; |
| 330 | } | |
| 331 | ||
| 332 | ||
| 333 | /** | |
| 334 | * Set the connection {@link SelectionKey}. | |
| 335 | * @param key - set this Context's SelectionKey | |
| 336 | */ | |
| 337 | public void setSelectionKey(SelectionKey key) { | |
| 338 | 231945 | this.key = key; |
| 339 | 231945 | } |
| 340 | ||
| 341 | ||
| 342 | /** | |
| 343 | * Return the current {@link Controller}. | |
| 344 | * @return - this Context's current {@link Controller} | |
| 345 | */ | |
| 346 | public Controller getController() { | |
| 347 | 302630 | return controller; |
| 348 | } | |
| 349 | ||
| 350 | ||
| 351 | /** | |
| 352 | * Set the current {@link Controller}. | |
| 353 | * @param {@link Controller} | |
| 354 | */ | |
| 355 | public void setController(Controller controller) { | |
| 356 | 427668 | this.controller = controller; |
| 357 | 427668 | } |
| 358 | ||
| 359 | ||
| 360 | /** | |
| 361 | * Recycle this instance. | |
| 362 | */ | |
| 363 | public void recycle(){ | |
| 364 | 161370 | if (isSuspended){ |
| 365 | 0 | throw new IllegalStateException("The Context has been marked as " + |
| 366 | "suspended and cannot be recycled"); | |
| 367 | } | |
| 368 | ||
| 369 | 161370 | getProtocolChainInstanceHandler().offer(protocolChain); |
| 370 | 161370 | key = null; |
| 371 | 161370 | keyRegistrationState = KeyRegistrationState.REGISTER; |
| 372 | 161370 | currentOpType = null; |
| 373 | 161369 | protocolChain = null; |
| 374 | 161368 | ioEvent = null; |
| 375 | 161370 | asyncQueueReader = null; |
| 376 | 161370 | asyncQueueWriter = null; |
| 377 | 161370 | if (attributes != null) { |
| 378 | 128305 | attributes.clear(); |
| 379 | } | |
| 380 | 161370 | isSuspended = false; |
| 381 | 161370 | refCounter.set(1); |
| 382 | 161370 | } |
| 383 | ||
| 384 | ||
| 385 | /** | |
| 386 | * Return {@link SelectionKey}'s next registration state. | |
| 387 | * @return this Context's SelectionKey registration state | |
| 388 | */ | |
| 389 | public KeyRegistrationState getKeyRegistrationState() { | |
| 390 | 143908 | return keyRegistrationState; |
| 391 | } | |
| 392 | ||
| 393 | ||
| 394 | /** | |
| 395 | * Set the {@link SelectionKey}'s next registration state | |
| 396 | * @param {@link keyRegistrationState} - set this Context's SelectionKey | |
| 397 | * registration state | |
| 398 | */ | |
| 399 | public void setKeyRegistrationState(KeyRegistrationState keyRegistrationState) { | |
| 400 | 53253 | this.keyRegistrationState = keyRegistrationState; |
| 401 | 53253 | } |
| 402 | ||
| 403 | ||
| 404 | /** | |
| 405 | * Return {@link ProtocolChain} executed by this instance. | |
| 406 | * @return {@link ProtocolChain} instance | |
| 407 | */ | |
| 408 | public ProtocolChain getProtocolChain() { | |
| 409 | 107406 | return protocolChain; |
| 410 | } | |
| 411 | ||
| 412 | ||
| 413 | /** | |
| 414 | * Set the {@link ProtocolChain} used by this {@link Context}. | |
| 415 | * @param protocolChain instance of {@link ProtocolChain} to be used by the Context | |
| 416 | */ | |
| 417 | public void setProtocolChain(ProtocolChain protocolChain) { | |
| 418 | 70566 | this.protocolChain = protocolChain; |
| 419 | 70566 | } |
| 420 | ||
| 421 | ||
| 422 | /** | |
| 423 | * Get the current {@link SelectionKey} interest ops this instance is executing. | |
| 424 | * @return OpType the currentOpType. | |
| 425 | */ | |
| 426 | public OpType getCurrentOpType() { | |
| 427 | 96226 | return currentOpType; |
| 428 | } | |
| 429 | ||
| 430 | ||
| 431 | /** | |
| 432 | * Set the current OpType value. | |
| 433 | * @param currentOpType sets current operation type | |
| 434 | */ | |
| 435 | public void setCurrentOpType(OpType currentOpType) { | |
| 436 | 161367 | this.currentOpType = currentOpType; |
| 437 | 161367 | } |
| 438 | ||
| 439 | ||
| 440 | /** | |
| 441 | * Configure the {@link #currentOpType} based on the | |
| 442 | * {@link SelectionKey#readyOps()} values. | |
| 443 | * @param key | |
| 444 | */ | |
| 445 | protected void configureOpType(SelectionKey key) { | |
| 446 | 12 | int readyOps = key.readyOps(); |
| 447 | 12 | switch (readyOps){ |
| 448 | case SelectionKey.OP_CONNECT: | |
| 449 | 0 | currentOpType = OpType.OP_CONNECT; |
| 450 | 0 | break; |
| 451 | case SelectionKey.OP_READ: | |
| 452 | 12 | currentOpType = OpType.OP_READ; |
| 453 | 12 | break; |
| 454 | case SelectionKey.OP_WRITE: | |
| 455 | 0 | currentOpType = OpType.OP_WRITE; |
| 456 | 0 | break; |
| 457 | case (SelectionKey.OP_WRITE | SelectionKey.OP_READ): | |
| 458 | 0 | currentOpType = OpType.OP_READ_WRITE; |
| 459 | 0 | break; |
| 460 | case (SelectionKey.OP_ACCEPT): | |
| 461 | 0 | currentOpType = OpType.OP_ACCEPT; |
| 462 | 0 | break; |
| 463 | /** | |
| 464 | * Fallback to an upcoming OP_CONNECT ops. This happens | |
| 465 | * because the {@link SocketChannel#finishConnect()} has not yet | |
| 466 | * been invoked. | |
| 467 | * | |
| 468 | */ | |
| 469 | default: | |
| 470 | 0 | currentOpType = OpType.OP_CONNECT; |
| 471 | break; | |
| 472 | ||
| 473 | } | |
| 474 | 12 | } |
| 475 | ||
| 476 | ||
| 477 | ||
| 478 | /** | |
| 479 | * Execute this Context using the Controller's Pipeline | |
| 480 | * @throws {@link PipelineFullException} | |
| 481 | * @deprecated | |
| 482 | */ | |
| 483 | public void execute() throws PipelineFullException { | |
| 484 | // If a IOEvent has been defined, invoke it first and | |
| 485 | // let its associated CallbackHandler decide if the ProtocolChain | |
| 486 | // be invoked or not. | |
| 487 | 0 | Object attachment = SelectionKeyAttachment.getAttachment(key); |
| 488 | 0 | if (ioEvent != null && (attachment instanceof CallbackHandler)) { |
| 489 | 0 | CallbackHandlerContextTask task = CallbackHandlerContextTask.poll(); |
| 490 | 0 | task.setCallBackHandler((CallbackHandler) attachment); |
| 491 | 0 | execute(task); |
| 492 | 0 | } else { |
| 493 | 0 | execute(ProtocolChainContextTask.poll()); |
| 494 | } | |
| 495 | 0 | } |
| 496 | ||
| 497 | ||
| 498 | /** | |
| 499 | * Execute this Context using the Controller's Pipeline | |
| 500 | * @param contextTask {@link ContextTask}, which will be | |
| 501 | * executed by {@link Pipeline} | |
| 502 | * @throws {@link PipelineFullException} | |
| 503 | */ | |
| 504 | public void execute(ContextTask contextTask) throws PipelineFullException { | |
| 505 | 102744 | execute(contextTask, true); |
| 506 | 102744 | } |
| 507 | ||
| 508 | ||
| 509 | /** | |
| 510 | * Execute this Context using either Controller's Pipeline or current thread | |
| 511 | * @param contextTask {@link ContextTask}, which will be | |
| 512 | * executed by {@link Pipeline} | |
| 513 | * @param runInSeparateThread if true - {@link ContextTask} will | |
| 514 | * be executed in separate thread, false - in current thread. | |
| 515 | * @throws {@link PipelineFullException} | |
| 516 | */ | |
| 517 | @SuppressWarnings("unchecked") | |
| 518 | public void execute(ContextTask contextTask, boolean runInSeparateThread) throws PipelineFullException { | |
| 519 | 161370 | if (protocolChain == null){ |
| 520 | ProtocolChainInstanceHandler | |
| 521 | 90804 | pciHandler = getProtocolChainInstanceHandler(); |
| 522 | 90804 | protocolChain = pciHandler.poll(); |
| 523 | } | |
| 524 | ||
| 525 | 161370 | if (contextTask != null) { |
| 526 | 161370 | contextTask.setContext(this); |
| 527 | 161370 | if (runInSeparateThread) { |
| 528 | 161370 | getPipeline().execute(contextTask); |
| 529 | } else { | |
| 530 | try { | |
| 531 | 0 | contextTask.call(); |
| 532 | 0 | } catch(Exception e) { |
| 533 | 0 | Controller.logger().log(Level.SEVERE, |
| 534 | "Unexpected exception occured, when executing task: " + | |
| 535 | contextTask, e); | |
| 536 | 0 | } |
| 537 | } | |
| 538 | } | |
| 539 | 161370 | } |
| 540 | ||
| 541 | ||
| 542 | /** | |
| 543 | * Return the {@link ProtocolChainInstanceListener} associated with this | |
| 544 | * {@link Context} | |
| 545 | * @return ProtocolChainInstanceListener | |
| 546 | */ | |
| 547 | public ProtocolChainInstanceHandler getProtocolChainInstanceHandler() { | |
| 548 | 252174 | ProtocolChainInstanceHandler protocolChainInstanceHandler = |
| 549 | selectorHandler.getProtocolChainInstanceHandler(); | |
| 550 | 252173 | return protocolChainInstanceHandler != null ? |
| 551 | protocolChainInstanceHandler : | |
| 552 | controller.getProtocolChainInstanceHandler(); | |
| 553 | } | |
| 554 | ||
| 555 | ||
| 556 | /** | |
| 557 | * Return the {@link Pipeline} executing this instance. | |
| 558 | * @return {@link Pipeline} | |
| 559 | */ | |
| 560 | public Pipeline getPipeline() { | |
| 561 | 161370 | if (pipeline == null && controller != null){ |
| 562 | 90874 | pipeline = controller.getPipeline(); |
| 563 | } | |
| 564 | 161370 | return pipeline; |
| 565 | } | |
| 566 | ||
| 567 | ||
| 568 | /** | |
| 569 | * Set the {@link Pipeline} that will execute this instance. | |
| 570 | * @param pipeline the {@link Pipeline} to set | |
| 571 | */ | |
| 572 | public void setPipeline(Pipeline pipeline) { | |
| 573 | 90804 | this.pipeline = pipeline; |
| 574 | 90804 | } |
| 575 | ||
| 576 | ||
| 577 | /** | |
| 578 | * Set an optional CallbackHandler. | |
| 579 | * @param ioEvent the {@link IOEvent} to set | |
| 580 | */ | |
| 581 | protected void setIOEvent(IOEvent<Context> ioEvent){ | |
| 582 | 58626 | this.ioEvent = ioEvent; |
| 583 | 58626 | } |
| 584 | ||
| 585 | /** | |
| 586 | * Return the current {@link IOEvent} associated with this | |
| 587 | * instance. | |
| 588 | * @return IOEvent the current {@link IOEvent} associated with this | |
| 589 | * instance. | |
| 590 | */ | |
| 591 | protected IOEvent getIOEvent(){ | |
| 592 | 58626 | return ioEvent; |
| 593 | } | |
| 594 | ||
| 595 | ||
| 596 | /** | |
| 597 | * Return the current {@link Controller#Protocol} this instance is executing. | |
| 598 | * @return the current Controller.Protocol this instance is executing. | |
| 599 | */ | |
| 600 | public Controller.Protocol getProtocol() { | |
| 601 | 133799 | return selectorHandler.protocol(); |
| 602 | } | |
| 603 | ||
| 604 | ||
| 605 | /** | |
| 606 | * @Deprecated | |
| 607 | * | |
| 608 | * Set the current {@link Controller#Protocol} this instance is executing. | |
| 609 | * @param protocol The current protocol. | |
| 610 | */ | |
| 611 | public void setProtocol(Controller.Protocol protocol) { | |
| 612 | 0 | } |
| 613 | ||
| 614 | ||
| 615 | /** | |
| 616 | * Return the current {@link SelectorHandler} this instance is executing. | |
| 617 | * @return the current {@link SelectorHandler} this instance is executing. | |
| 618 | */ | |
| 619 | public SelectorHandler getSelectorHandler() { | |
| 620 | 426589 | return selectorHandler; |
| 621 | } | |
| 622 | ||
| 623 | /** | |
| 624 | * Set the current {@link SelectorHandler} this instance is executing. | |
| 625 | * @param selectorHandler {@link SelectorHandler} | |
| 626 | */ | |
| 627 | public void setSelectorHandler(SelectorHandler selectorHandler) { | |
| 628 | 486285 | this.selectorHandler = selectorHandler; |
| 629 | 486285 | } |
| 630 | ||
| 631 | ||
| 632 | /** | |
| 633 | * Returns {@link AsyncQueueReadable}, assciated with the current | |
| 634 | * {@link Context}. This method is not threadsafe. | |
| 635 | * | |
| 636 | * @return {@link AsyncQueueReadable} | |
| 637 | */ | |
| 638 | public AsyncQueueReadable getAsyncQueueReadable() { | |
| 639 | 0 | if (asyncQueueReadable == null) { |
| 640 | 0 | asyncQueueReadable = new AsyncQueueReadableContextWrapper(); |
| 641 | } | |
| 642 | ||
| 643 | 0 | return asyncQueueReadable; |
| 644 | } | |
| 645 | ||
| 646 | /** | |
| 647 | * Returns {@link AsyncQueueWritable}, assciated with the current | |
| 648 | * {@link Context}. This method is not threadsafe. | |
| 649 | * | |
| 650 | * @return {@link AsyncQueueWritable} | |
| 651 | */ | |
| 652 | public AsyncQueueWritable getAsyncQueueWritable() { | |
| 653 | 86662 | if (asyncQueueWritable == null) { |
| 654 | 41 | asyncQueueWritable = new AsyncQueueWritableContextWrapper(); |
| 655 | } | |
| 656 | ||
| 657 | 86662 | return asyncQueueWritable; |
| 658 | } | |
| 659 | ||
| 660 | /** | |
| 661 | * Return the {@linkAsyncQueueReader} | |
| 662 | * @return the {@linkAsyncQueueReader} | |
| 663 | */ | |
| 664 | protected AsyncQueueReader getAsyncQueueReader() { | |
| 665 | 0 | return asyncQueueReader; |
| 666 | } | |
| 667 | ||
| 668 | /** | |
| 669 | * Set the {@linkAsyncQueueReader} | |
| 670 | * @param asyncQueueReader {@linkAsyncQueueReader} | |
| 671 | */ | |
| 672 | protected void setAsyncQueueReader(AsyncQueueReader asyncQueueReader) { | |
| 673 | 161370 | this.asyncQueueReader = asyncQueueReader; |
| 674 | 161370 | } |
| 675 | ||
| 676 | /** | |
| 677 | * Return the {@linkAsyncQueueWriter} | |
| 678 | * @return the {@linkAsyncQueueWriter} | |
| 679 | */ | |
| 680 | protected AsyncQueueWriter getAsyncQueueWriter() { | |
| 681 | 0 | return asyncQueueWriter; |
| 682 | } | |
| 683 | ||
| 684 | /** | |
| 685 | * Set the {@linkAsyncQueueWriter} | |
| 686 | * @param asyncQueueWriter {@linkAsyncQueueWriter} | |
| 687 | */ | |
| 688 | protected void setAsyncQueueWriter(AsyncQueueWriter asyncQueueWriter) { | |
| 689 | 161370 | this.asyncQueueWriter = asyncQueueWriter; |
| 690 | 161370 | } |
| 691 | ||
| 692 | 82 | private class AsyncQueueWritableContextWrapper implements AsyncQueueWritable { |
| 693 | /** | |
| 694 | * {@inheritDoc} | |
| 695 | */ | |
| 696 | public void writeToAsyncQueue(ByteBuffer buffer) throws IOException { | |
| 697 | 0 | asyncQueueWriter.write(key, buffer); |
| 698 | 0 | } |
| 699 | ||
| 700 | /** | |
| 701 | * {@inheritDoc} | |
| 702 | */ | |
| 703 | public void writeToAsyncQueue(ByteBuffer buffer, | |
| 704 | AsyncWriteCallbackHandler callbackHandler) throws IOException { | |
| 705 | 0 | asyncQueueWriter.write(key, buffer, callbackHandler); |
| 706 | 0 | } |
| 707 | ||
| 708 | /** | |
| 709 | * {@inheritDoc} | |
| 710 | */ | |
| 711 | public void writeToAsyncQueue(ByteBuffer buffer, | |
| 712 | AsyncWriteCallbackHandler callbackHandler, | |
| 713 | AsyncQueueDataProcessor writePreProcessor) throws IOException { | |
| 714 | 0 | asyncQueueWriter.write(key, buffer, callbackHandler, writePreProcessor); |
| 715 | 0 | } |
| 716 | ||
| 717 | /** | |
| 718 | * {@inheritDoc} | |
| 719 | */ | |
| 720 | public void writeToAsyncQueue(ByteBuffer buffer, | |
| 721 | AsyncWriteCallbackHandler callbackHandler, | |
| 722 | AsyncQueueDataProcessor writePreProcessor, | |
| 723 | boolean isCloneByteBuffer) throws IOException { | |
| 724 | 66662 | asyncQueueWriter.write(key, buffer, callbackHandler, |
| 725 | writePreProcessor, isCloneByteBuffer); | |
| 726 | 66662 | } |
| 727 | ||
| 728 | /** | |
| 729 | * {@inheritDoc} | |
| 730 | */ | |
| 731 | public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer) | |
| 732 | throws IOException { | |
| 733 | 0 | asyncQueueWriter.write(key, dstAddress, buffer); |
| 734 | 0 | } |
| 735 | ||
| 736 | /** | |
| 737 | * {@inheritDoc} | |
| 738 | */ | |
| 739 | public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, | |
| 740 | AsyncWriteCallbackHandler callbackHandler) throws IOException { | |
| 741 | 0 | asyncQueueWriter.write(key, dstAddress, buffer, |
| 742 | callbackHandler); | |
| 743 | 0 | } |
| 744 | ||
| 745 | /** | |
| 746 | * {@inheritDoc} | |
| 747 | */ | |
| 748 | public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, | |
| 749 | AsyncWriteCallbackHandler callbackHandler, | |
| 750 | AsyncQueueDataProcessor writePreProcessor) throws IOException { | |
| 751 | 0 | asyncQueueWriter.write(key, dstAddress, buffer, |
| 752 | callbackHandler, writePreProcessor); | |
| 753 | 0 | } |
| 754 | ||
| 755 | /** | |
| 756 | * {@inheritDoc} | |
| 757 | */ | |
| 758 | public void writeToAsyncQueue(SocketAddress dstAddress, ByteBuffer buffer, | |
| 759 | AsyncWriteCallbackHandler callbackHandler, | |
| 760 | AsyncQueueDataProcessor writePreProcessor, boolean isCloneByteBuffer) | |
| 761 | throws IOException { | |
| 762 | 20000 | asyncQueueWriter.write(key, dstAddress, buffer, |
| 763 | callbackHandler, writePreProcessor, isCloneByteBuffer); | |
| 764 | 20000 | } |
| 765 | } | |
| 766 | ||
| 767 | 0 | private class AsyncQueueReadableContextWrapper implements AsyncQueueReadable { |
| 768 | /** | |
| 769 | * {@inheritDoc} | |
| 770 | */ | |
| 771 | public void readFromAsyncQueue(ByteBuffer buffer, | |
| 772 | AsyncReadCallbackHandler callbackHandler) throws IOException { | |
| 773 | 0 | asyncQueueReader.read(key, buffer, callbackHandler); |
| 774 | 0 | } |
| 775 | ||
| 776 | /** | |
| 777 | * {@inheritDoc} | |
| 778 | */ | |
| 779 | public void readFromAsyncQueue(ByteBuffer buffer, | |
| 780 | AsyncReadCallbackHandler callbackHandler, | |
| 781 | AsyncReadCondition condition) throws IOException { | |
| 782 | 0 | asyncQueueReader.read(key, buffer, callbackHandler, condition); |
| 783 | 0 | } |
| 784 | ||
| 785 | /** | |
| 786 | * {@inheritDoc} | |
| 787 | */ | |
| 788 | public void readFromAsyncQueue(ByteBuffer buffer, | |
| 789 | AsyncReadCallbackHandler callbackHandler, | |
| 790 | AsyncReadCondition condition, | |
| 791 | AsyncQueueDataProcessor readPostProcessor) throws IOException { | |
| 792 | 0 | asyncQueueReader.read(key, buffer, callbackHandler, |
| 793 | condition, readPostProcessor); | |
| 794 | 0 | } |
| 795 | } | |
| 796 | ||
| 797 | ||
| 798 | /** | |
| 799 | * Suspend the execution of this {@link Context}. Suspending the execution | |
| 800 | * allow application to store the current instance, and re-use it later | |
| 801 | * by not only the Thread used when called suspend, but also from any other Thread. | |
| 802 | * A suspended Context will not be re-used by any other transaction and Thread. | |
| 803 | * A suspended Context will keep its current state intact, meaning its | |
| 804 | * SelectionKey, attributes, SelectorHandler, etc, will not change. Internally, | |
| 805 | * The Context will not be recyled and will not be re-used by any Thread. | |
| 806 | * | |
| 807 | * When invoked this method will automatically set the | |
| 808 | * {@link Context#setKeyRegistrationState} to {@link KeyRegistrationState} | |
| 809 | * to KeyRegistrationState.NONE. | |
| 810 | * | |
| 811 | * Invoking this method many times as not effect once suspended. | |
| 812 | */ | |
| 813 | public void suspend(){ | |
| 814 | 0 | if (isSuspended) return; |
| 815 | 0 | isSuspended = true; |
| 816 | 0 | incrementRefCount(); |
| 817 | 0 | setKeyRegistrationState(keyRegistrationState.NONE); |
| 818 | 0 | } |
| 819 | ||
| 820 | ||
| 821 | /** | |
| 822 | * Return <tt>true</tt> if this Context has been suspended by | |
| 823 | * invoking {@link suspend}. When suspended, invoking {@link Context#recycle} | |
| 824 | * will throw an {@link IllegalStateException} | |
| 825 | * @return <tt>true</tt> if this Context has been suspended | |
| 826 | */ | |
| 827 | public boolean isSuspended(){ | |
| 828 | 0 | return isSuspended; |
| 829 | } | |
| 830 | ||
| 831 | ||
| 832 | /** | |
| 833 | * Resume a {@link #suspend}ed {@link Context}. | |
| 834 | * <strong>Resume will not call {@link Context#recycle}</strong>. So | |
| 835 | * after the caller is finished using Context caller must | |
| 836 | * call {@link Controller#returnContext(com.sun.grizzly.Context)} | |
| 837 | * to mark it as a candidate for being re-used by another Thread and connection. | |
| 838 | * | |
| 839 | * <strong>Important. When resumed, all operations done on this | |
| 840 | * object are not thread-safe and there is probability that another | |
| 841 | * thread is already using this object. Never use this object once resumed.</strong> | |
| 842 | * | |
| 843 | * When invoked this method will automatically set the | |
| 844 | * {@link Context#setKeyRegistrationState} to {@link KeyRegistrationState} | |
| 845 | * to KeyRegistrationState.REGISTER and automatically re-enable read and | |
| 846 | * write operations. | |
| 847 | * | |
| 848 | * If the Context hasn't been suspended, calling that method has no effet. | |
| 849 | */ | |
| 850 | public void resume(){ | |
| 851 | 0 | if (!isSuspended) return; |
| 852 | 0 | isSuspended = false; |
| 853 | 0 | selectorHandler.register(key, SelectionKey.OP_READ); |
| 854 | 0 | } |
| 855 | ||
| 856 | ||
| 857 | /** | |
| 858 | * Cancel a {@link #suspend}ed {@link Context}. Invoking this method will | |
| 859 | * automatically clean the state of this Context and mark it as a candidate | |
| 860 | * for being re-used by another Thread and connection. | |
| 861 | * | |
| 862 | * <strong>Important. When cancelled, all operations done on this | |
| 863 | * object are not thread-safe and there is probability that another | |
| 864 | * thread is already using this object. Never use this object once cancelled.</strong> | |
| 865 | * | |
| 866 | * | |
| 867 | * When invoked this method will automatically close the underlying | |
| 868 | * connection (represented by its {@link SelectionKey}. | |
| 869 | * | |
| 870 | * If the Context hasn't been suspended, calling that method has no effet. | |
| 871 | */ | |
| 872 | public void cancel(){ | |
| 873 | 0 | if (!isSuspended) return; |
| 874 | 0 | isSuspended = false; |
| 875 | 0 | selectorHandler.getSelectionKeyHandler().cancel(key); |
| 876 | 0 | getController().returnContext(this); |
| 877 | 0 | } |
| 878 | /** | |
| 879 | * Called by outer Threads that are not instances of {@link WorkerThread} to | |
| 880 | * indicate that this {@link Context} should not be | |
| 881 | * {@link #recycle()} or offered back to its pool. | |
| 882 | * | |
| 883 | * When a outer Thread is done with {@link Context} it must call | |
| 884 | * {@link Controller#returnContext(com.sun.grizzly.Context) to | |
| 885 | * ensure that {@link Context} will be properly recycled. | |
| 886 | * | |
| 887 | * @return Current Thread reference count | |
| 888 | */ | |
| 889 | public void incrementRefCount(){ | |
| 890 | 0 | refCounter.incrementAndGet(); |
| 891 | 0 | } |
| 892 | ||
| 893 | /** | |
| 894 | * Decrements the reference count of this {@link Context}. | |
| 895 | * Threads wanting to release {@link Context} should not call | |
| 896 | * this method but instead use | |
| 897 | * {@link Controller#returnContext(com.sun.grizzly.Context)} | |
| 898 | * @return return decremented reference count | |
| 899 | */ | |
| 900 | public int decrementRefCount(){ | |
| 901 | 161370 | return refCounter.decrementAndGet(); |
| 902 | } | |
| 903 | ||
| 904 | } |