# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: C:\Projects\Grizzly\trunk\modules\grizzly\src # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java --- main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Base (BASE) +++ main/java/com/sun/grizzly/async/AsyncQueueReaderContextTask.java Locally Modified (Based On LOCAL) @@ -23,7 +23,7 @@ package com.sun.grizzly.async; -import com.sun.grizzly.ContextTask; +import com.sun.grizzly.SelectionKeyContextTask; import java.nio.channels.SelectionKey; @@ -35,11 +35,11 @@ * * @author Alexey Stashok */ -public class AsyncQueueReaderContextTask extends ContextTask { +public class AsyncQueueReaderContextTask extends SelectionKeyContextTask { private static final TaskPool taskPool = new TaskPool() { @Override - public AsyncQueueReaderContextTask newTask() { + public AsyncQueueReaderContextTask newInstance() { return new AsyncQueueReaderContextTask(); } }; @@ -55,7 +55,7 @@ taskPool.offer(contextTask); } - public Object call() throws Exception { + public Object doCall() throws Exception { try { SelectionKey selectionKey = context.getSelectionKey(); if (selectionKey == null) { Index: main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java --- main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Base (BASE) +++ main/java/com/sun/grizzly/async/AsyncQueueWriterContextTask.java Locally Modified (Based On LOCAL) @@ -23,7 +23,7 @@ package com.sun.grizzly.async; -import com.sun.grizzly.ContextTask; +import com.sun.grizzly.SelectionKeyContextTask; import java.nio.channels.SelectionKey; @@ -35,11 +35,11 @@ * * @author Alexey Stashok */ -public class AsyncQueueWriterContextTask extends ContextTask { +public class AsyncQueueWriterContextTask extends SelectionKeyContextTask { private static final TaskPool taskPool = new TaskPool() { @Override - public AsyncQueueWriterContextTask newTask() { + public AsyncQueueWriterContextTask newInstance() { return new AsyncQueueWriterContextTask(); } }; @@ -55,7 +55,7 @@ taskPool.offer(contextTask); } - public Object call() throws Exception { + protected Object doCall() throws Exception { try { SelectionKey selectionKey = context.getSelectionKey(); if (selectionKey == null) { Index: main/java/com/sun/grizzly/CallbackHandlerContextTask.java --- main/java/com/sun/grizzly/CallbackHandlerContextTask.java Base (BASE) +++ main/java/com/sun/grizzly/CallbackHandlerContextTask.java Locally Modified (Based On LOCAL) @@ -33,11 +33,11 @@ * * @author Alexey Stashok */ -public class CallbackHandlerContextTask extends ContextTask { +public class CallbackHandlerContextTask extends SelectionKeyContextTask { private static final TaskPool taskPool = new TaskPool() { @Override - public CallbackHandlerContextTask newTask() { + public CallbackHandlerContextTask newInstance() { return new CallbackHandlerContextTask(); } }; @@ -53,7 +53,7 @@ taskPool.offer(contextTask); } - public Object call() throws Exception { + protected Object doCall() throws Exception { IOEvent ioEvent = context.getIOEvent(); OpType currentOpType = context.getCurrentOpType(); @@ -93,6 +93,4 @@ callBackHandler = null; super.recycle(); } - - } Index: main/java/com/sun/grizzly/Context.java --- main/java/com/sun/grizzly/Context.java Base (BASE) +++ main/java/com/sun/grizzly/Context.java Locally Modified (Based On LOCAL) @@ -32,6 +32,7 @@ import com.sun.grizzly.async.AsyncReadCondition; import com.sun.grizzly.async.AsyncWriteCallbackHandler; import com.sun.grizzly.util.AttributeHolder; +import com.sun.grizzly.util.SelectionKeyAttachment; import java.io.IOException; import java.net.SocketAddress; import java.nio.ByteBuffer; @@ -373,7 +374,7 @@ // If a IOEvent has been defined, invoke it first and // let its associated CallbackHandler decide if the ProtocolChain // be invoked or not. - Object attachment = key.attachment(); + Object attachment = SelectionKeyAttachment.getAttachment(key); if (ioEvent != null && (attachment instanceof CallbackHandler)) { CallbackHandlerContextTask task = CallbackHandlerContextTask.poll(); task.setCallBackHandler((CallbackHandler) attachment); Index: main/java/com/sun/grizzly/ContextTask.java --- main/java/com/sun/grizzly/ContextTask.java Base (BASE) +++ main/java/com/sun/grizzly/ContextTask.java Locally Modified (Based On LOCAL) @@ -23,6 +23,7 @@ package com.sun.grizzly; +import com.sun.grizzly.util.ConcurrentLinkedQueuePool; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; @@ -47,24 +48,13 @@ context = null; } - protected abstract static class TaskPool { - private ConcurrentLinkedQueue pool = - new ConcurrentLinkedQueue(); + protected abstract static class TaskPool + extends ConcurrentLinkedQueuePool { - public abstract E newTask(); - - public E poll() { - E task = pool.poll(); - if (task == null) { - task = newTask(); - } - - return task; - } - + @Override public void offer(E task) { task.recycle(); - pool.offer(task); + super.offer(task); } } } Index: main/java/com/sun/grizzly/Controller.java --- main/java/com/sun/grizzly/Controller.java Base (BASE) +++ main/java/com/sun/grizzly/Controller.java Locally Modified (Based On LOCAL) @@ -25,6 +25,7 @@ import com.sun.grizzly.util.AttributeHolder; import com.sun.grizzly.util.Cloner; +import com.sun.grizzly.util.ConcurrentLinkedQueuePool; import com.sun.grizzly.util.Copyable; import com.sun.grizzly.util.State; import com.sun.grizzly.util.StateHolder; @@ -135,7 +136,7 @@ /** * A cached list of Context. Context are by default stateless. */ - private ConcurrentLinkedQueue contexts; + private ConcurrentLinkedQueuePool contexts; /** @@ -239,7 +240,13 @@ * Controller constructor */ public Controller() { - contexts = new ConcurrentLinkedQueue(); + contexts = new ConcurrentLinkedQueuePool() { + @Override + public Context newInstance() { + return new Context(); + } + }; + stateHolder = new StateHolder(true); } @@ -262,10 +269,8 @@ ProtocolChainInstanceHandler pciHandler = null; ProtocolChain protocolChain = null; Context serverCtx = contexts.poll(); - if (serverCtx == null){ - serverCtx = new Context(); serverCtx.setController(this); - } + serverCtx.setSelectorHandler(selectorHandler); try { @@ -474,9 +479,6 @@ */ public Context pollContext(SelectionKey key){ Context ctx = contexts.poll(); - if (ctx == null){ - ctx = new Context(); - } ctx.setController(this); ctx.setSelectionKey(key); return ctx; Index: main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java --- main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Base (BASE) +++ main/java/com/sun/grizzly/DefaultSelectionKeyHandler.java Locally Modified (Based On LOCAL) @@ -23,8 +23,9 @@ package com.sun.grizzly; +import com.sun.grizzly.util.SelectionKeyAttachment; +import com.sun.grizzly.util.SelectionKeyActionAttachment; import com.sun.grizzly.util.Copyable; -import com.sun.grizzly.util.ThreadAttachment; import java.io.IOException; import java.net.Socket; import java.nio.channels.ClosedChannelException; @@ -34,11 +35,7 @@ import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLSession; -import static com.sun.grizzly.filter.SSLReadFilter.EXPIRE_TIME; -import com.sun.grizzly.util.WorkerThread; import java.nio.channels.Selector; /** @@ -103,6 +100,12 @@ * {@inheritDoc} */ public void process(SelectionKey key) { + Object attachment = key.attachment(); + + if (attachment instanceof SelectionKeyActionAttachment) { + ((SelectionKeyActionAttachment) attachment).process(key); + } + removeExpirationStamp(key); } @@ -238,6 +241,11 @@ closeChannel(key.channel()); } + Object attachment = key.attachment(); + if (attachment instanceof SelectionKeyAttachment) { + ((SelectionKeyAttachment) attachment).release(); + } + key.attach(null); key.cancel(); key = null; @@ -309,13 +317,8 @@ if (attachment != null) { if (attachment instanceof Long) { key.attach(null); - } else if (attachment instanceof ThreadAttachment) { - ((WorkerThread) Thread.currentThread()).attach( - (ThreadAttachment) attachment); - key.attach(null); - } else if (attachment instanceof SSLEngine) { - SSLEngine sslEngine = (SSLEngine) attachment; - sslEngine.getSession().removeValue(EXPIRE_TIME); + } else if (attachment instanceof SelectionKeyAttachment) { + ((SelectionKeyAttachment) attachment).setTimeout(null); } } } @@ -331,11 +334,8 @@ Object attachment = key.attachment(); if (attachment == null) { key.attach(currentTime); - } else if (attachment instanceof ThreadAttachment) { - ((ThreadAttachment) attachment).setTimeout(currentTime); - } else if (attachment instanceof SSLEngine) { - SSLEngine sslEngine = (SSLEngine) attachment; - sslEngine.getSession().putValue(EXPIRE_TIME,currentTime); + } else if (attachment instanceof SelectionKeyAttachment) { + ((SelectionKeyAttachment) attachment).setTimeout(currentTime); } } @@ -356,17 +356,9 @@ // can't predict the type of the attached object. if (attachment instanceof Long) { return (Long) attachment; - } else if (attachment instanceof SSLEngine) { - SSLSession sslSession = ((SSLEngine) attachment).getSession(); - if (sslSession != null && - sslSession.getValue(EXPIRE_TIME) != null) { - return (Long) sslSession.getValue(EXPIRE_TIME); + } else if (attachment instanceof SelectionKeyAttachment) { + return ((SelectionKeyAttachment) attachment).getTimeout(); } - - return null; - } else if (attachment instanceof ThreadAttachment) { - return ((ThreadAttachment) attachment).getTimeout(); - } } catch (ClassCastException ex) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, Index: main/java/com/sun/grizzly/filter/SSLReadFilter.java --- main/java/com/sun/grizzly/filter/SSLReadFilter.java Base (BASE) +++ main/java/com/sun/grizzly/filter/SSLReadFilter.java Locally Modified (Based On LOCAL) @@ -27,7 +27,9 @@ import com.sun.grizzly.Controller; import com.sun.grizzly.ProtocolFilter; import com.sun.grizzly.SSLConfig; +import com.sun.grizzly.util.SSLSelectionKeyAttachment; import com.sun.grizzly.util.SSLUtils; +import com.sun.grizzly.util.SelectionKeyAttachment; import com.sun.grizzly.util.WorkerThreadImpl; import java.io.EOFException; import java.io.IOException; @@ -49,14 +51,6 @@ * @author Jeanfrancois Arcand */ public class SSLReadFilter implements ProtocolFilter{ - - public final static String HANDSHAKE = "handshake"; - public final static String DATA_DECODED = "dataDecoded"; - public final static String INPUT_BB_REMAINDER = "inputBBRemainder"; - public final static String OUTPUT_BB_REMAINDER = "outputBBRemainder"; - - - /** * The SSLContext associated with the SSL implementation * we are running on. @@ -95,12 +89,6 @@ /** - * Session keep-alive flag. - */ - public final static String EXPIRE_TIME = "expireTime"; - - - /** * Has the enabled protocol configured. */ private boolean isProtocolConfigured = false; @@ -125,7 +113,6 @@ public boolean execute(Context ctx) throws IOException { boolean result = true; int count = 0; - boolean isCopied = false; Throwable exception = null; SelectionKey key = ctx.getSelectionKey(); WorkerThreadImpl workerThread; @@ -137,22 +124,16 @@ SSLEngine sslEngine = newSSLEngine(key); workerThread.setSSLEngine(sslEngine); - key.attach(sslEngine); + SSLSelectionKeyAttachment.attach(key, sslEngine); - boolean hasHandshake = Boolean.TRUE.equals( - sslEngine.getSession().getValue(HANDSHAKE)); - - restoreSecuredBufferRemainders(sslEngine); + boolean hasHandshake = sslEngine.getSession().isValid(); try { allocateBuffers(); - isCopied = copyByteBufferToInputBB(sslEngine, - workerThread.getByteBuffer(), workerThread.getInputBB()); if (hasHandshake) { count = doRead(key); } else if (doHandshake(key, SSLUtils.getReadTimeout())) { hasHandshake = true; - sslEngine.getSession().putValue(HANDSHAKE, Boolean.TRUE); // set "no available data" for secured output buffer ByteBuffer outputBB = workerThread.getOutputBB(); @@ -168,12 +149,6 @@ log("SSLReadFilter.execute",ex); } finally { if (exception != null || count == -1){ - if (isCopied) { - /* if some data was copied from ByteBuffer, - * but connection got closed - clean inputBB */ - workerThread.getInputBB().clear(); - } - ctx.setAttribute(Context.THROWABLE,exception); ctx.setKeyRegistrationState( Context.KeyRegistrationState.CANCEL); @@ -199,8 +174,7 @@ cancel(ctx.getSelectionKey()); } else if (ctx.getKeyRegistrationState() == Context.KeyRegistrationState.REGISTER){ - SSLEngine sslEngine = (SSLEngine) ctx.getSelectionKey().attachment(); - saveSecuredBufferRemainders(sslEngine); + saveSecuredBufferRemainders(ctx.getSelectionKey()); ctx.getSelectorHandler().register(ctx.getSelectionKey(), SelectionKey.OP_READ); ctx.setKeyRegistrationState(Context.KeyRegistrationState.NONE); @@ -295,20 +269,20 @@ } - private static int doRead(SelectionKey key){ + private static int doRead(SelectionKey key) { final WorkerThreadImpl workerThread = - (WorkerThreadImpl)Thread.currentThread(); + (WorkerThreadImpl) Thread.currentThread(); ByteBuffer byteBuffer = workerThread.getByteBuffer(); ByteBuffer outputBB = workerThread.getOutputBB(); ByteBuffer inputBB = workerThread.getInputBB(); SSLEngine sslEngine = workerThread.getSSLEngine(); int count = -1; - try{ + try { // Read first bytes to avoid continuing if the client // closed the connection. - count = ((SocketChannel)key.channel()).read(inputBB); - if (count != -1){ + count = ((SocketChannel) key.channel()).read(inputBB); + if (count != -1) { // Decrypt the bytes we just read. if (Controller.logger().isLoggable(Level.FINE)) { Controller.logger().log(Level.FINE, @@ -318,21 +292,20 @@ } byteBuffer = - SSLUtils.unwrapAll(byteBuffer,inputBB,sslEngine); + SSLUtils.unwrapAll(byteBuffer, inputBB, sslEngine); workerThread.setInputBB(inputBB); workerThread.setOutputBB(outputBB); workerThread.setByteBuffer(byteBuffer); } return count; - } catch(IOException ex){ + } catch (IOException ex) { log("Exception during SSL read.", ex); return -1; } finally { - if (count == -1){ - try{ + if (count == -1) { + try { sslEngine.closeInbound(); - } catch (SSLException ex){ - ; + } catch (SSLException ex) { } } } @@ -399,13 +372,12 @@ SSLEngine sslEngine = null; if (key.attachment() == null){ sslEngine = newSSLEngine(); - } else if (key.attachment() instanceof SSLEngine){ - sslEngine = (SSLEngine)key.attachment(); + } else if (key.attachment() instanceof SSLSelectionKeyAttachment){ + sslEngine = ((SSLSelectionKeyAttachment) SelectionKeyAttachment.getAttachment(key)).getSslEngine(); } else { sslEngine = newSSLEngine(); } sslEngine.setWantClientAuth(wantClientAuth); - sslEngine.getSession().removeValue(EXPIRE_TIME); sslEngine.setNeedClientAuth(needClientAuth); return sslEngine; } @@ -613,78 +585,28 @@ return ciphers; } - /** - * If bytebuffer is not empty it means that previous - * ProtocolFilters has read some data already. This data - * should be copied to the inputBB. - */ - private static boolean copyByteBufferToInputBB(SSLEngine sslEngine, - ByteBuffer byteBuffer, ByteBuffer inputBB) { - if (byteBuffer.position() > 0) { - Boolean isDataDecoded = - (Boolean) sslEngine.getSession().getValue(DATA_DECODED); + private void saveSecuredBufferRemainders(SelectionKey selectionKey) { + SSLSelectionKeyAttachment attachment = + (SSLSelectionKeyAttachment) selectionKey.attachment(); - if (!Boolean.TRUE.equals(isDataDecoded)) { - byteBuffer.flip(); - inputBB.put(byteBuffer); - byteBuffer.clear(); - return true; - } else if (isDataDecoded != null) { - sslEngine.getSession().removeValue(DATA_DECODED); - } - } - - return false; - } - - /** - * Restores (if required) secure buffers, associated with SSLEngine, - * which were saved during previous SSLReadFilter execution. - * It makes possible data, which wasn't processed on previous cycle to be processed now - */ - private void restoreSecuredBufferRemainders(SSLEngine sslEngine) { - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread(); - - ByteBuffer inputBBRemainder = (ByteBuffer) sslEngine.getSession(). - getValue(INPUT_BB_REMAINDER); - if (inputBBRemainder != null) { - sslEngine.getSession().removeValue(INPUT_BB_REMAINDER); - workerThread.setInputBB(inputBBRemainder); - } - - ByteBuffer outputBBRemainder = (ByteBuffer) sslEngine.getSession(). - getValue(OUTPUT_BB_REMAINDER); - if (outputBBRemainder != null) { - sslEngine.getSession().removeValue(OUTPUT_BB_REMAINDER); - workerThread.setOutputBB(outputBBRemainder); - } - } - - /** - * Saves (if required) secure buffers, associated with SSLEngine - * If secured data, associated with SSLEngine, is not completely - * processed now (may be additional data is required) - then it could be processed - * on next SSLReadFilter execution. - */ - private void saveSecuredBufferRemainders(SSLEngine sslEngine) { - WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread(); - - if (sslEngine == null) { + if (attachment == null) { Controller.logger().log(Level.FINE, - "SSLEngine is NULL, when saving buffers"); + "SelectionKey attachment is NULL, when saving buffers"); return; } + WorkerThreadImpl workerThread = (WorkerThreadImpl) Thread.currentThread(); + ByteBuffer inputBB = workerThread.getInputBB(); if (inputBB != null && inputBB.hasRemaining()) { - sslEngine.getSession().putValue(INPUT_BB_REMAINDER, inputBB); workerThread.setInputBB(null); + attachment.setInputBB(inputBB); } ByteBuffer outputBB = workerThread.getOutputBB(); if (outputBB != null && outputBB.hasRemaining()) { - sslEngine.getSession().putValue(OUTPUT_BB_REMAINDER, outputBB); workerThread.setOutputBB(null); + attachment.setOutputBB(outputBB); } } Index: main/java/com/sun/grizzly/ProtocolChainContextTask.java --- main/java/com/sun/grizzly/ProtocolChainContextTask.java Base (BASE) +++ main/java/com/sun/grizzly/ProtocolChainContextTask.java Locally Modified (Based On LOCAL) @@ -24,8 +24,6 @@ package com.sun.grizzly; -import java.nio.channels.SelectionKey; - /** * ProtocolChain task, which will be executed by * Context, when Context.execute(ContextTask) @@ -33,11 +31,11 @@ * * @author Alexey Stashok */ -public class ProtocolChainContextTask extends ContextTask { +public class ProtocolChainContextTask extends SelectionKeyContextTask { private static final TaskPool taskPool = new TaskPool() { @Override - public ProtocolChainContextTask newTask() { + public ProtocolChainContextTask newInstance() { return new ProtocolChainContextTask(); } }; @@ -51,16 +49,10 @@ taskPool.offer(contextTask); } - public Object call() throws Exception { - SelectionKey currentKey = context.getSelectionKey(); - SelectionKeyHandler selectionKeyHandler = context. - getSelectorHandler().getSelectionKeyHandler(); - - selectionKeyHandler.process(currentKey); + protected Object doCall() throws Exception { try { context.getProtocolChain().execute(context); } finally { - selectionKeyHandler.postProcess(currentKey); offer(this); } Index: main/java/com/sun/grizzly/SelectionKeyContextTask.java --- main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New +++ main/java/com/sun/grizzly/SelectionKeyContextTask.java Locally New @@ -0,0 +1,66 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.grizzly; + +import java.nio.channels.SelectionKey; + +/** + * Basic class for all ContextTasks, which are dealing with + * SelectionKeys + * + * @author Alexey Stashok + */ +public abstract class SelectionKeyContextTask extends ContextTask { + + public final Object call() throws Exception { + Object result = null; + SelectionKey currentKey = context.getSelectionKey(); + SelectionKeyHandler selectionKeyHandler = context. + getSelectorHandler().getSelectionKeyHandler(); + + selectionKeyHandler.process(currentKey); + try { + result = doCall(); + } finally { + selectionKeyHandler.postProcess(currentKey); + } + + return result; + } + + protected abstract Object doCall() throws Exception; +} Index: main/java/com/sun/grizzly/TCPSelectorHandler.java --- main/java/com/sun/grizzly/TCPSelectorHandler.java Base (BASE) +++ main/java/com/sun/grizzly/TCPSelectorHandler.java Locally Modified (Based On LOCAL) @@ -31,6 +31,7 @@ import com.sun.grizzly.async.TCPAsyncQueueReader; import com.sun.grizzly.util.Cloner; import com.sun.grizzly.util.Copyable; +import com.sun.grizzly.util.SelectionKeyAttachment; import com.sun.grizzly.util.SelectionKeyOP; import com.sun.grizzly.util.SelectionKeyOP.ConnectSelectionKeyOP; import com.sun.grizzly.util.State; @@ -610,7 +611,7 @@ throws IOException{ // disable OP_READ on key before doing anything else key.interestOps(key.interestOps() & (~SelectionKey.OP_READ)); - Object attach = key.attachment(); + Object attach = SelectionKeyAttachment.getAttachment(key); if (asyncQueueReader.isAsyncQueueReaderEnabledFor(key)) { final Context context = pollContext(ctx, key); @@ -646,7 +647,8 @@ context.setCurrentOpType(Context.OpType.OP_WRITE); invokeAsyncQueueWriter(context); return false; - } else if ((attach = key.attachment()) instanceof CallbackHandler){ + } else if ((attach = SelectionKeyAttachment.getAttachment(key)) + instanceof CallbackHandler){ final Context context = pollContext(ctx, key); context.setCurrentOpType(Context.OpType.OP_WRITE); invokeCallbackHandler((CallbackHandler) attach, context); @@ -671,7 +673,7 @@ key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE)); key.interestOps(key.interestOps() & (~SelectionKey.OP_READ)); - Object attach = key.attachment(); + Object attach = SelectionKeyAttachment.getAttachment(key); if (attach instanceof CallbackHandler){ final Context context = pollContext(ctx, key); context.setCurrentOpType(Context.OpType.OP_CONNECT); Index: main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java --- main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New +++ main/java/com/sun/grizzly/util/ConcurrentLinkedQueuePool.java Locally New @@ -0,0 +1,60 @@ +/* + * The contents of this file are subject to the terms + * of the Common Development and Distribution License + * (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the license at + * https://glassfish.dev.java.net/public/CDDLv1.0.html or + * glassfish/bootstrap/legal/CDDLv1.0.txt. + * See the License for the specific language governing + * permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL + * Header Notice in each file and include the License file + * at glassfish/bootstrap/legal/CDDLv1.0.txt. + * If applicable, add the following below the CDDL Header, + * with the fields enclosed by brackets [] replaced by + * you own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + */ + +package com.sun.grizzly.util; + +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * ObjectPool implementation based on ConcurrentLinkedQueue + * + * @author Alexey Stashok + */ +public abstract class ConcurrentLinkedQueuePool implements ObjectPool { + private volatile ConcurrentLinkedQueue pool; + + public abstract E newInstance(); + + public E poll() { + if (pool == null) { + synchronized(this) { + if (pool == null) { + pool = new ConcurrentLinkedQueue(); + } + } + } + + E object = pool.poll(); + if (object == null) { + object = newInstance(); + } + + return object; + } + + public void offer(E object) { + if (pool != null) { + pool.offer(object); + } + } +} Index: main/java/com/sun/grizzly/util/ObjectPool.java --- main/java/com/sun/grizzly/util/ObjectPool.java Locally New +++ main/java/com/sun/grizzly/util/ObjectPool.java Locally New @@ -0,0 +1,35 @@ +/* + * The contents of this file are subject to the terms + * of the Common Development and Distribution License + * (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the license at + * https://glassfish.dev.java.net/public/CDDLv1.0.html or + * glassfish/bootstrap/legal/CDDLv1.0.txt. + * See the License for the specific language governing + * permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL + * Header Notice in each file and include the License file + * at glassfish/bootstrap/legal/CDDLv1.0.txt. + * If applicable, add the following below the CDDL Header, + * with the fields enclosed by brackets [] replaced by + * you own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + */ + +package com.sun.grizzly.util; + +/** + * Basic interface for object pool implementations + * + * @author Alexey Stashok + */ +public interface ObjectPool { + public E poll(); + + public void offer(E object); +} Index: main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java --- main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New +++ main/java/com/sun/grizzly/util/SelectionKeyActionAttachment.java Locally New @@ -0,0 +1,50 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.grizzly.util; + +import java.nio.channels.SelectionKey; + +/** + * Class represents extended version of SelectionKeyAttachment, + * and introduces process method, which will be called by framework once + * SelectionKey has some ready event, before actual event processing. + * + * @author Alexey Stashok + */ +public abstract class SelectionKeyActionAttachment extends SelectionKeyAttachment { + public abstract void process(SelectionKey selectionKey); +} Index: main/java/com/sun/grizzly/util/SelectionKeyAttachment.java --- main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New +++ main/java/com/sun/grizzly/util/SelectionKeyAttachment.java Locally New @@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.grizzly.util; + +import java.nio.channels.SelectionKey; + +/** + * Basic class for all SelectionKey attachments. + * Custom attachments should be inherited from it. + * + * @author Alexey Stashok + */ +public abstract class SelectionKeyAttachment { + private Long timeout; + + public static Object getAttachment(SelectionKey key) { + Object attachment = key.attachment(); + if (attachment instanceof SelectionKeyAttachmentWrapper) { + return ((SelectionKeyAttachmentWrapper) attachment).getAttachment(); + } + + return attachment; + } + + public Long getTimeout() { + return timeout; + } + + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + + public void release() { + timeout = null; + } +} Index: main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java --- main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New +++ main/java/com/sun/grizzly/util/SelectionKeyAttachmentWrapper.java Locally New @@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.grizzly.util; + +import java.nio.channels.SelectionKey; + +/** + * SelectionKey attachment utility class. + * This class could be used as wrapper for custom SelectionKey + * attachments, which are not subclasses of SelectionKeyAttachment + * class. + * + * @author Alexey Stashok + */ +public class SelectionKeyAttachmentWrapper extends SelectionKeyActionAttachment { + private E attachment; + + public E getAttachment() { + return attachment; + } + + public void setAttachment(E attachment) { + this.attachment = attachment; + } + + @Override + public void process(SelectionKey selectionKey) { + // Do nothing by default + } + + @Override + public void release() { + attachment = null; + super.release(); + } +} Index: main/java/com/sun/grizzly/util/SelectionKeyOP.java --- main/java/com/sun/grizzly/util/SelectionKeyOP.java Base (BASE) +++ main/java/com/sun/grizzly/util/SelectionKeyOP.java Locally Modified (Based On LOCAL) @@ -27,7 +27,6 @@ import java.net.SocketAddress; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; -import java.util.concurrent.ConcurrentLinkedQueue; /** * @@ -38,27 +37,29 @@ private SelectionKey key; private SelectableChannel channel; - private static ConcurrentLinkedQueue readWritePool = - new ConcurrentLinkedQueue(); + private static ConcurrentLinkedQueuePool readWritePool = + new ConcurrentLinkedQueuePool() { + @Override + public SelectionKeyOP newInstance() { + return new SelectionKeyOP(); + } + }; - private static ConcurrentLinkedQueue connectPool = - new ConcurrentLinkedQueue(); + private static ConcurrentLinkedQueuePool connectPool = + new ConcurrentLinkedQueuePool() { + @Override + public SelectionKeyOP newInstance() { + return new ConnectSelectionKeyOP(); + } + }; public static SelectionKeyOP aquireSelectionKeyOP(int op) { if (op == SelectionKey.OP_READ || op == SelectionKey.OP_WRITE || op == (SelectionKey.OP_WRITE | SelectionKey.OP_READ)) { SelectionKeyOP operation = readWritePool.poll(); - if (operation == null) { - operation = new SelectionKeyOP(); - } - return operation; } else if (op == SelectionKey.OP_CONNECT) { SelectionKeyOP operation = connectPool.poll(); - if (operation == null) { - operation = new ConnectSelectionKeyOP(); - } - \ No newline at end of file return operation; } Index: main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java --- main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New +++ main/java/com/sun/grizzly/util/SSLSelectionKeyAttachment.java Locally New @@ -0,0 +1,145 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.grizzly.util; + +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import javax.net.ssl.SSLEngine; + +/** + * SelectionKeyAttachment implementation, which is targeted for SSL + * support. + * + * @author Alexey Stashok + */ +public class SSLSelectionKeyAttachment extends SelectionKeyActionAttachment { + + private static ConcurrentLinkedQueuePool pool = + new ConcurrentLinkedQueuePool() { + + @Override + public SSLSelectionKeyAttachment newInstance() { + return new SSLSelectionKeyAttachment(); + } + }; + private SSLEngine sslEngine; + private ByteBuffer inputBB; + private ByteBuffer outputBB; + + /** + * Saves (if required) secure buffers, associated with SSLEngine + * If secured data, associated with SSLEngine, is not completely + * processed now (may be additional data is required) - then it could be processed + * on next SSLReadFilter execution. + */ + public static void attach(SelectionKey key, SSLEngine sslEngine) { + SSLSelectionKeyAttachment attachment = null; + Object currentAttachment = key.attachment(); + if (currentAttachment != null && + currentAttachment instanceof SSLSelectionKeyAttachment) { + attachment = (SSLSelectionKeyAttachment) currentAttachment; + } else { + attachment = pool.poll(); + } + + attachment.setInputBB(null); + attachment.setOutputBB(null); + + attachment.setSslEngine(sslEngine); + key.attach(attachment); + } + + public ByteBuffer getInputBB() { + return inputBB; + } + + public void setInputBB(ByteBuffer inputBB) { + this.inputBB = inputBB; + } + + public ByteBuffer getOutputBB() { + return outputBB; + } + + public void setOutputBB(ByteBuffer outputBB) { + this.outputBB = outputBB; + } + + public SSLEngine getSslEngine() { + return sslEngine; + } + + public void setSslEngine(SSLEngine sslEngine) { + this.sslEngine = sslEngine; + } + + /** + * Restores (if required) secure buffers, associated with SSLEngine, + * which were saved during previous SSLReadFilter execution. + * It makes possible data, which wasn't processed on previous cycle to be processed now + */ + @Override + public void process(SelectionKey selectionKey) { + WorkerThreadImpl workerThread; + try { + workerThread = (WorkerThreadImpl) Thread.currentThread(); + } catch (ClassCastException ex) { + throw new IllegalStateException(ex.getMessage()); + } + + if (inputBB != null) { + workerThread.setInputBB(inputBB); + inputBB = null; + } + + if (outputBB != null) { + workerThread.setOutputBB(outputBB); + outputBB = null; + } + + workerThread.setSSLEngine(sslEngine); + } + + @Override + public void release() { + sslEngine = null; + inputBB = null; + outputBB = null; + super.release(); + pool.offer(this); + } + } Index: main/java/com/sun/grizzly/util/ThreadAttachment.java --- main/java/com/sun/grizzly/util/ThreadAttachment.java Base (BASE) +++ main/java/com/sun/grizzly/util/ThreadAttachment.java Locally Modified (Based On LOCAL) @@ -23,6 +23,7 @@ package com.sun.grizzly.util; import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; import java.util.WeakHashMap; import javax.net.ssl.SSLEngine; @@ -32,12 +33,9 @@ * * @author Jeanfrancois Arcand */ -public class ThreadAttachment { +public class ThreadAttachment extends SelectionKeyActionAttachment { - private long timeout; - - private String threadId; @@ -169,22 +167,13 @@ this.threadId = threadId; } - /** - * Set the timeout used by the SelectionKeyHandler to times out an idle - * connection. + * SelectionKey attachment processing + * @param selectionKey */ - public void setTimeout(long timeout){ - this.timeout = timeout; + public void process(SelectionKey selectionKey) { + ((WorkerThread) Thread.currentThread()).attach( + (ThreadAttachment) this); + selectionKey.attach(null); } - - - /** - * Return the timeout used by the SelectionKeyHandler to times out an idle - * connection. - */ - public long getTimeout(){ - return timeout; } - -} Index: main/java/com/sun/grizzly/util/WorkerThreadImpl.java --- main/java/com/sun/grizzly/util/WorkerThreadImpl.java Base (BASE) +++ main/java/com/sun/grizzly/util/WorkerThreadImpl.java Locally Modified (Based On LOCAL) @@ -294,11 +294,11 @@ * @return a new ThreadAttachment */ public ThreadAttachment detach(boolean copyState) { - if (threadAttachment == null){ + if (threadAttachment == null) { threadAttachment = new ThreadAttachment(); } - try{ + try { threadAttachment.setByteBuffer(byteBuffer); threadAttachment.setSSLEngine(sslEngine); threadAttachment.setInputBB(inputBB); @@ -308,7 +308,7 @@ } finally { // We cannot cache/re-use this object as it might be referenced // by more than one thread. - if (copyState){ + if (copyState) { // Re-create a new ByteBuffer byteBuffer = ByteBufferFactory.allocate(byteBufferType, initialByteBufferSize);