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 | } |