Hi,
recently I've commited ConnectionManagement/Cache code provided by Ken,
but didn't commit integration part.
Here I would like to describe how I see the integration separately for
server and client sides.
1) Server side ConnectionManagement/caching.
Think appropriate place for integrating server side connection
management is SelectionKeyHandler.
Instance of this class is able to track operations with SelectionKey
like: process()*, postProcess()*, cancel()
* - new methods I propose to add to SelectionKeyHandler interface.
How-to-use:
Set appropriate SelectionKeyHandler to controller.
-----------------------------------------------------------------
controller.setSelectionKeyHandler(
new CacheableSelectionKeyHandler(highWatermark,
numberToReclaim));
-----------------------------------------------------------------
2) Client side ConnectionManagement/caching.
As for client side, I've created new abstraction called
ConnectorHandlerPool, which is used by client side to acquire and
release ConnectorHandlers, which actually represent client connection unit.
I left default implementation, which we provided in Controller as
default one, but created new CacheableConnectorHandlerPool, which
instantiates CacheableConnectorHandler, which in there turn can deal
with connection cache and either create new or reuse existing connections.
How-to-use:
Set appropriate ConnectorHandlerPool to controller.
-----------------------------------------------------------------
controller.setConnectorHandlerPool(new
CacheableConnectorHandlerPool(controller,
HIGH_WATERMARK, NUMBER_TO_RECLAIM, MAX_PARALLEL));
-----------------------------------------------------------------
It's highlevel :) overview. Changes I propose are attached as svn diff file.
Comments are welcome :)
WBR,
Alexey.
# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly
# 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: connectioncache/client/CacheableConnectorHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\client\CacheableConnectorHandler.java Locally New
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\client\CacheableConnectorHandler.java Locally New
***************
*** 1,0 ****
--- 1,320 ----
+ /*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ */
+
+ package com.sun.grizzly.connectioncache.client;
+
+ import com.sun.grizzly.*;
+ import com.sun.grizzly.Controller.Protocol;
+ import com.sun.grizzly.connectioncache.spi.transport.Connection;
+ import com.sun.grizzly.connectioncache.spi.transport.ContactInfo;
+ import com.sun.grizzly.connectioncache.spi.transport.OutboundConnectionCache;
+ import java.io.IOException;
+ import java.net.SocketAddress;
+ import java.nio.ByteBuffer;
+ import java.nio.channels.SelectableChannel;
+ import java.nio.channels.SelectionKey;
+ import java.nio.channels.Selector;
+
+ /**
+ * Extended implementation of the DefaultSelectionKeyHandler with
+ * ConnectionManagement integrated in it
+ *
+ * @author Alexey Stashok
+ */
+ public class CacheableConnectorHandler implements ConnectorHandler<SelectorHandler>,
+ ContactInfo, Connection {
+ private SocketAddress targetAddress;
+ private Controller controller;
+ private ConnectorHandlerPool protocolConnectorHandlerPool;
+ private Protocol protocol;
+ private ConnectorHandler underlyingConnectorHandler;
+
+ private OutboundConnectionCache<ConnectorHandler> connectionCache;
+
+ private ConnectExecutor connectExecutor;
+
+ public CacheableConnectorHandler(Controller controller,
+ ConnectorHandlerPool protocolConnectorHandlerPool,
+ OutboundConnectionCache connectionCache) {
+ this.controller = controller;
+ this.protocolConnectorHandlerPool = protocolConnectorHandlerPool;
+ this.connectionCache = connectionCache;
+ connectExecutor = new ConnectExecutor();
+ }
+
+ public void setProtocol(Protocol protocol) {
+ this.protocol = protocol;
+ }
+
+ public Protocol protocol() {
+ return protocol;
+ }
+
+ // connect method #1
+ public void connect(SocketAddress remoteAddress, CallbackHandler callbackHandler,SelectorHandler selectorHandler) throws IOException {
+ connectExecutor.setParameters(remoteAddress, callbackHandler, selectorHandler);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect(callbackHandler, selectorHandler);
+ }
+ }
+
+ // connect method #2
+ public void connect(SocketAddress remoteAddress, CallbackHandler callbackHandler) throws IOException {
+ connectExecutor.setParameters(remoteAddress, callbackHandler);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect(callbackHandler);
+ }
+ }
+
+ // connect method #3
+ public void connect(SocketAddress remoteAddress) throws IOException {
+ connectExecutor.setParameters(remoteAddress);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect();
+ }
+ }
+
+ // connect method #4
+ public void connect(SocketAddress remoteAddress, SocketAddress localAddress,
+ CallbackHandler callbackHandler, SelectorHandler selectorHandler) throws IOException {
+ connectExecutor.setParameters(remoteAddress, localAddress, callbackHandler, selectorHandler);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect(callbackHandler, selectorHandler);
+ }
+ }
+
+ // connect method #5
+ public void connect(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler) throws IOException {
+ connectExecutor.setParameters(remoteAddress, localAddress, callbackHandler);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect(callbackHandler);
+ }
+ }
+
+ // connect method #6
+ public void connect(SocketAddress remoteAddress, SocketAddress localAddress) throws IOException {
+ connectExecutor.setParameters(remoteAddress, localAddress);
+ if (doConnect(remoteAddress)) {
+ notifyCallbackHandlerConnect();
+ }
+ }
+
+ /**
+ * @param targetAddress target connection address
+ * @return true if Connection was taken from cache, otherwise false
+ * @throws java.io.IOException if IO error happened
+ */
+ private boolean doConnect(SocketAddress targetAddress) throws IOException {
+ this.targetAddress = targetAddress;
+ underlyingConnectorHandler = connectionCache.get(this);
+
+ /* will be null if new underlying connector handler was created
+ * if != null - it means underlyingConnectorHandler was
+ * taken from cache */
+ return !connectExecutor.wasCalled();
+ }
+
+
+ public void close() throws IOException {
+ connectionCache.release(underlyingConnectorHandler, 0);
+ protocolConnectorHandlerPool.releaseConnectorHandler(underlyingConnectorHandler);
+ }
+
+ public void register(CallbackHandler callbackHandler) {
+ underlyingConnectorHandler.register(callbackHandler);
+ }
+
+ public long read(ByteBuffer byteBuffer, boolean blocking) throws IOException {
+ return underlyingConnectorHandler.read(byteBuffer, blocking);
+ }
+
+ public long write(ByteBuffer byteBuffer, boolean blocking) throws IOException {
+ return underlyingConnectorHandler.write(byteBuffer, blocking);
+ }
+
+ public void finishConnect(SelectionKey key) {
+ underlyingConnectorHandler.finishConnect(key);
+ }
+
+ public void setController(Controller controller) {
+ underlyingConnectorHandler.setController(controller);
+ }
+
+ public Controller getController() {
+ return underlyingConnectorHandler.getController();
+ }
+
+ public SelectableChannel getUnderlyingChannel() {
+ return underlyingConnectorHandler.getUnderlyingChannel();
+ }
+
+ public CallbackHandler getCallbackHandler() {
+ return underlyingConnectorHandler.getCallbackHandler();
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ underlyingConnectorHandler.setCallbackHandler(callbackHandler);
+ }
+
+ public Connection createConnection() throws IOException {
+ underlyingConnectorHandler = protocolConnectorHandlerPool.acquireConnectorHandler(protocol);
+
+ connectExecutor.setConnectorHandler(underlyingConnectorHandler);
+ connectExecutor.invoke();
+ return underlyingConnectorHandler;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getName());
+ sb.append(" targetAddress: ");
+ sb.append(targetAddress);
+ sb.append(" protocol: ");
+ sb.append(protocol);
+ sb.append(" hashCode: ");
+ sb.append(super.hashCode());
+ return sb.toString();
+ }
+
+ public int hashCode() {
+ return targetAddress.hashCode() ^ protocol.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o instanceof CacheableConnectorHandler) {
+ CacheableConnectorHandler handler = (CacheableConnectorHandler) o;
+ return targetAddress.equals(handler.targetAddress) &&
+ protocol.equals(handler.protocol);
+ }
+
+ return false;
+ }
+
+ private void notifyCallbackHandlerConnect() {
+ CallbackHandler callbackHandler = new CallbackHandler<Context>(){
+ public void onConnect(IOEvent<Context> ioEvent) {
+ SelectionKey key = ioEvent.attachment().getSelectionKey();
+ finishConnect(key);
+ getController().registerKey(key,SelectionKey.OP_WRITE,
+ Protocol.TCP);
+ }
+ public void onRead(IOEvent<Context> ioEvent) {
+ }
+ public void onWrite(IOEvent<Context> ioEvent) {
+ }
+ };
+
+ notifyCallbackHandlerConnect(callbackHandler);
+ }
+
+ private void notifyCallbackHandlerConnect(CallbackHandler callbackHandler) {
+ notifyCallbackHandlerConnect(callbackHandler, controller.getSelectorHandler(protocol));
+ }
+
+ private void notifyCallbackHandlerConnect(CallbackHandler callbackHandler, SelectorHandler selectorHandler) {
+ underlyingConnectorHandler.setCallbackHandler(callbackHandler);
+ Selector protocolSelector = selectorHandler.getSelector();
+ SelectionKey key = underlyingConnectorHandler.getUnderlyingChannel().keyFor(protocolSelector);
+ final Context context = controller.pollContext(key);
+ callbackHandler.onConnect(new IOEvent<Context>() {
+ public Context attach(Context e) {
+ return context;
+ }
+
+ public Context attachment() {
+ return context;
+ }
+ });
+ }
+
+ private static class ConnectExecutor {
+ private int methodNumber;
+ private ConnectorHandler connectorHandler;
+ private SocketAddress remoteAddress;
+ private SocketAddress localAddress;
+ private CallbackHandler callbackHandler;
+ private SelectorHandler selectorHandler;
+ private boolean wasCalled;
+
+ public void setConnectorHandler(ConnectorHandler connectorHandler) {
+ this.connectorHandler = connectorHandler;
+ }
+
+ public void setParameters(SocketAddress remoteAddress, CallbackHandler callbackHandler, SelectorHandler selectorHandler) {
+ setParameters(remoteAddress, null, callbackHandler, selectorHandler);
+ methodNumber = 1;
+ }
+
+ public void setParameters(SocketAddress remoteAddress, CallbackHandler callbackHandler) {
+ setParameters(remoteAddress, null, callbackHandler);
+ methodNumber = 2;
+ }
+
+ public void setParameters(SocketAddress remoteAddress) {
+ setParameters(remoteAddress, (SocketAddress) null);
+ methodNumber = 3;
+ }
+
+ public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler,SelectorHandler selectorHandler) {
+ wasCalled = false;
+ this.remoteAddress = remoteAddress;
+ this.localAddress = localAddress;
+ this.callbackHandler = callbackHandler;
+ this.selectorHandler = selectorHandler;
+ methodNumber = 4;
+ }
+
+ public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress, CallbackHandler callbackHandler) {
+ setParameters(remoteAddress, localAddress, callbackHandler, null);
+ methodNumber = 5;
+ }
+
+ public void setParameters(SocketAddress remoteAddress, SocketAddress localAddress) {
+ setParameters(remoteAddress, localAddress, null);
+ methodNumber = 6;
+ }
+
+ public boolean wasCalled() {
+ return wasCalled;
+ }
+
+ public void invoke() throws IOException {
+ wasCalled = true;
+ switch(methodNumber) {
+ case 1: connectorHandler.connect(remoteAddress, callbackHandler, selectorHandler);
+ break;
+ case 2: connectorHandler.connect(remoteAddress, callbackHandler);
+ break;
+ case 3: connectorHandler.connect(remoteAddress);
+ break;
+ case 4: connectorHandler.connect(remoteAddress, localAddress, callbackHandler, selectorHandler);
+ break;
+ case 5: connectorHandler.connect(remoteAddress, localAddress, callbackHandler);
+ break;
+ case 6: connectorHandler.connect(remoteAddress, localAddress);
+ break;
+ default: throw new IllegalStateException("Can not find appropriate connect method: " + methodNumber);
+ }
+ }
+ }
+ }
Index: connectioncache/client/CacheableConnectorHandlerPool.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\client\CacheableConnectorHandlerPool.java Locally New
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\client\CacheableConnectorHandlerPool.java Locally New
***************
*** 1,0 ****
--- 1,79 ----
+ /*
+ * 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.connectioncache.client;
+
+ import com.sun.grizzly.*;
+ import com.sun.grizzly.Controller.Protocol;
+ import com.sun.grizzly.connectioncache.spi.transport.ConnectionCacheFactory;
+ import com.sun.grizzly.connectioncache.spi.transport.OutboundConnectionCache;
+
+ /**
+ * <code>ConnectorInstanceHandler</code> which use a
+ * <code>ConcurrentQueue</code> to pool <code>CacheableConnectorHandler</code>
+ *
+ * @author Alexey Stashok
+ */
+ public class CacheableConnectorHandlerPool implements
+ ConnectorHandlerPool<CacheableConnectorHandler> {
+
+ private Controller controller;
+ private ConnectorHandlerPool protocolConnectorHandlerPool;
+ private OutboundConnectionCache<ConnectorHandler> outboundConnectionCache;
+ private ConnectorInstanceHandler<CacheableConnectorHandler> connectorInstanceHandler;
+
+ public CacheableConnectorHandlerPool(Controller controller, int highWaterMark,
+ int numberToReclaim, int maxParallel) {
+ this.controller = controller;
+ this.outboundConnectionCache =
+ ConnectionCacheFactory.makeBlockingOutboundConnectionCache(
+ "Grizzly outbound connection cache", highWaterMark,
+ numberToReclaim, maxParallel, controller.logger());
+ protocolConnectorHandlerPool = new DefaultConnectorHandlerPool(controller);
+ connectorInstanceHandler = new CacheableConnectorInstanceHandler();
+ }
+
+ public CacheableConnectorHandler acquireConnectorHandler(Protocol protocol) {
+ CacheableConnectorHandler connectorHandler = connectorInstanceHandler.acquire();
+ connectorHandler.setProtocol(protocol);
+ return connectorHandler;
+ }
+
+ public void releaseConnectorHandler(CacheableConnectorHandler connectorHandler) {
+ connectorInstanceHandler.release(connectorHandler);
+ }
+
+ /**
+ * Default <code>ConnectorInstanceHandler</code> which use a
+ * <code>ConcurrentQueue</code> to pool <code>ConnectorHandler</code>
+ */
+ private class CacheableConnectorInstanceHandler extends
+ ConnectorInstanceHandler.ConcurrentQueueConnectorInstanceHandler<CacheableConnectorHandler> {
+
+ public CacheableConnectorHandler newInstance() {
+ return new CacheableConnectorHandler(controller,
+ protocolConnectorHandlerPool,
+ outboundConnectionCache);
+ }
+ }
+ }
Index: connectioncache/server/CacheableSelectionKeyHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\server\CacheableSelectionKeyHandler.java Locally New
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\connectioncache\server\CacheableSelectionKeyHandler.java Locally New
***************
*** 1,0 ****
--- 1,119 ----
+ /*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ */
+
+ package com.sun.grizzly.connectioncache.server;
+
+ import com.sun.grizzly.*;
+ import com.sun.grizzly.connectioncache.spi.transport.Connection;
+ import com.sun.grizzly.connectioncache.spi.transport.ConnectionCacheFactory;
+ import com.sun.grizzly.connectioncache.spi.transport.InboundConnectionCache;
+ import java.io.IOException;
+ import java.nio.channels.SelectableChannel;
+ import java.nio.channels.SelectionKey;
+ import java.util.Map;
+ import java.util.WeakHashMap;
+
+ /**
+ * Extended implementation of the DefaultSelectionKeyHandler with
+ * ConnectionManagement integrated in it
+ *
+ * @author Alexey Stashok
+ */
+ public class CacheableSelectionKeyHandler extends DefaultSelectionKeyHandler {
+ private InboundConnectionCache<ChannelWrapper> inboundConnectionCache;
+ private Map<SelectableChannel, ChannelWrapper> wrapperCache;
+ /**
+ * Construct ConnectionManagementSelectionKeyHandler
+ * @param highWaterMark max number of simultaneously open connections
+ * @param numberToReclaim number of connections to reclaim
+ */
+ public CacheableSelectionKeyHandler(int highWaterMark, int numberToReclaim) {
+ inboundConnectionCache = ConnectionCacheFactory.makeBlockingInboundConnectionCache(
+ "Grizzly inbound connection cache", highWaterMark,
+ numberToReclaim, getLogger());
+ wrapperCache = new WeakHashMap<SelectableChannel, ChannelWrapper>();
+ }
+
+ /**
+ * @Override
+ */
+ public void process(SelectionKey key) {
+ ChannelWrapper wrapper = getChannelWrapper(key.channel());
+ inboundConnectionCache.requestReceived(wrapper);
+ }
+
+ /**
+ * @Override
+ */
+ public void postProcess(SelectionKey key) {
+ ChannelWrapper wrapper = getChannelWrapper(key.channel());
+ inboundConnectionCache.requestProcessed(wrapper, 1);
+ inboundConnectionCache.responseSent(wrapper);
+ }
+
+ /**
+ * @Override
+ */
+ public void cancel(SelectionKey key) {
+ super.cancel(key);
+
+ ChannelWrapper wrapper = wrapperCache.remove(key.channel());
+ if (wrapper != null) {
+ inboundConnectionCache.close(wrapper);
+ }
+ }
+
+ private ChannelWrapper getChannelWrapper(SelectableChannel channel) {
+ ChannelWrapper wrapper = wrapperCache.get(channel);
+ if (wrapper == null) {
+ wrapper = new ChannelWrapper(channel);
+ wrapperCache.put(channel, wrapper);
+ }
+
+ return wrapper;
+ }
+
+ public class ChannelWrapper implements Connection {
+ private SelectableChannel channel;
+
+ public ChannelWrapper(SelectableChannel channel) {
+ this.channel = channel;
+ }
+
+ public void close() throws IOException {
+ closeChannel(channel);
+ }
+
+ public int hashCode() {
+ return channel.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o instanceof ChannelWrapper) {
+ return channel.equals(((ChannelWrapper) o).channel);
+ }
+
+ return false;
+ }
+ }
+ }
Index: ConnectorHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\ConnectorHandler.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\ConnectorHandler.java Locally Modified (Based On LOCAL)
***************
*** 22,30 ****
--- 22,32 ----
*/
package com.sun.grizzly;
+ import com.sun.grizzly.connectioncache.spi.transport.Connection;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
+ import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
/**
***************
*** 38,44 ****
*
* @author Jeanfrancois Arcand
*/
! public interface ConnectorHandler<E extends SelectorHandler> extends Handler{
/**
--- 40,46 ----
*
* @author Jeanfrancois Arcand
*/
! public interface ConnectorHandler<E extends SelectorHandler> extends Handler, Connection {
/**
***************
*** 156,163 ****
/**
* Close the underlying connection.
*/
! public void close() throws IOException;
/**
--- 158,166 ----
/**
* Close the underlying connection.
+ * @throws java.io.IOException
*/
! public void close() throws IOException;
/**
***************
*** 174,182 ****
--- 177,209 ----
/**
* Return the <code>Controller</code>
+ * @return
*/
public Controller getController();
+ /**
+ * Method returns underlying <code>ConnectorHandler</code>'s channel
+ * @return channel
+ */
+ public SelectableChannel getUnderlyingChannel();
+
+ /**
+ * Returns <code>ConnectorHandler</code>'s callback handler instance,
+ * which is used to process occuring events
+ *
+ * @return callback handler
+ */
+ public CallbackHandler getCallbackHandler();
+
+ /**
+ * Sets <code>ConnectorHandler</code>'s callback handler instance,
+ * which is used to process occuring events
+ *
+ * @param callbackHandler handler
+ */
+ public void setCallbackHandler(CallbackHandler callbackHandler);
}
Index: Context.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\Context.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\Context.java Locally Modified (Based On LOCAL)
***************
*** 195,209 ****
--- 195,218 ----
/**
* Execute the <code>ProtocolChain</code>.
+ * @throws java.lang.Exception Exception thrown by protocol chain
*/
public Object call() throws Exception {
+ SelectionKey key = this.key;
+ controller.getSelectionKeyHandler().process(key);
+ try {
protocolChain.execute(this);
+ } finally {
+ controller.getSelectionKeyHandler().postProcess(key);
+ }
+
return null;
}
/**
* Return <code>ProtocolChain</code> executed by this instance.
+ * @return <code>ProtocolChain</code> instance
*/
public ProtocolChain getProtocolChain() {
return protocolChain;
***************
*** 212,217 ****
--- 221,227 ----
/**
* Set the <code>ProtocolChain</code> used by this <code>Context</code>.
+ * @param protocolChain instance of <code>ProtocolChain</code> to be used by the Context
*/
public void setProtocolChain(ProtocolChain protocolChain) {
this.protocolChain = protocolChain;
***************
*** 229,234 ****
--- 239,245 ----
/**
* Set the current OpType value.
+ * @param currentOpType sets current operation type
*/
protected void setCurrentOpType(OpType currentOpType) {
this.currentOpType = currentOpType;
***************
*** 237,242 ****
--- 248,254 ----
/**
* Execute this Context using the Controller's Pipeline
+ * @throws com.sun.grizzly.PipelineFullException
*/
public void execute() throws PipelineFullException{
controller.getPipeline().execute(this);
Index: DefaultSelectionKeyHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\DefaultSelectionKeyHandler.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\DefaultSelectionKeyHandler.java Locally Modified (Based On LOCAL)
***************
*** 62,69 ****
--- 62,80 ----
public DefaultSelectionKeyHandler() {
}
+ /**
+ * {_at_inheritDoc}
+ */
+ public void process(SelectionKey key) {
+ }
/**
+ * {_at_inheritDoc}
+ */
+ public void postProcess(SelectionKey key) {
+ }
+
+ /**
* Expire a SelectionKey. If a SelectionKey is inactive for 30 seconds,
* the SelectionKey will be cancelled and its associated Channel closed.
* @param key <code>SelectionKey</code> to expire
***************
*** 109,143 ****
return;
}
! SelectableChannel channel = key.channel();
! if (channel instanceof SocketChannel) {
! Socket socket = ((SocketChannel) channel).socket();
- try{
- socket.shutdownInput();
- } catch (IOException ex){
- ;
- }
-
- try{
- socket.shutdownOutput();
- } catch (IOException ex){
- ;
- }
-
- try{
- socket.close();
- } catch (IOException ex){
- ;
- } finally {
- try{
- key.channel().close();
- } catch (IOException ex){
- ; // LOG ME
- }
- }
- }
-
key.attach(null);
key.cancel();
key = null;
--- 120,130 ----
return;
}
! closeChannel(key.channel());
key.attach(null);
key.cancel();
***************
*** 163,169 ****
--- 147,183 ----
this.timeout = timeout;
}
+ protected void closeChannel(SelectableChannel channel) {
+ if (channel instanceof SocketChannel) {
+ Socket socket = ((SocketChannel) channel).socket();
+
+ try{
+ socket.shutdownInput();
+ } catch (IOException ex){
+ ;
}
+
+ try{
+ socket.shutdownOutput();
+ } catch (IOException ex){
+ ;
+ }
+
+ try{
+ socket.close();
+ } catch (IOException ex){
+ ;
+ }
+ }
+
+ try{
+ channel.close();
+ } catch (IOException ex){
+ ; // LOG ME
+ }
+ }
+ }
Index: SelectionKeyHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\SelectionKeyHandler.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\SelectionKeyHandler.java Locally Modified (Based On LOCAL)
***************
*** 34,39 ****
--- 34,51 ----
public interface SelectionKeyHandler extends Handler{
/**
+ * <code>SelectionKey</code> process notification
+ * @param key <code>SelectionKey</code> to process
+ */
+ public void process(SelectionKey key);
+
+ /**
+ * <code>SelectionKey</code> post process notification
+ * @param key <code>SelectionKey</code> to process
+ */
+ public void postProcess(SelectionKey key);
+
+ /**
* Expire a SelectionKey.
* @param key <code>SelectionKey</code> to expire
*/
Index: TCPConnectorHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\TCPConnectorHandler.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\TCPConnectorHandler.java Locally Modified (Based On LOCAL)
***************
*** 30,35 ****
--- 30,36 ----
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.NotYetConnectedException;
+ import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CountDownLatch;
***************
*** 443,449 ****
--- 444,463 ----
this.controller = controller;
}
+ public SelectableChannel getUnderlyingChannel() {
+ return socketChannel;
}
+
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+ }
Index: UDPConnectorHandler.java
*** C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\UDPConnectorHandler.java Base (BASE)
--- C:\Projects\Grizzly\trunk\modules\grizzly\src\main\java\com\sun\grizzly\UDPConnectorHandler.java Locally Modified (Based On LOCAL)
***************
*** 30,35 ****
--- 30,36 ----
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.NotYetConnectedException;
+ import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.DatagramChannel;
import java.util.concurrent.CountDownLatch;
***************
*** 230,243 ****
pipeline.startPipeline();
controller.setPipeline(pipeline);
! callbackHandler = new CallbackHandler<SelectionKey>(){
! public void onConnect(IOEvent<SelectionKey> ioEvent) {
! SelectionKey key = ioEvent.attachment();
finishConnect(key);
}
! public void onRead(IOEvent<SelectionKey> ioEvent) {
}
! public void onWrite(IOEvent<SelectionKey> ioEvent) {
}
};
--- 231,244 ----
pipeline.startPipeline();
controller.setPipeline(pipeline);
! callbackHandler = new CallbackHandler<Context>(){
! public void onConnect(IOEvent<Context> ioEvent) {
! SelectionKey key = ioEvent.attachment().getSelectionKey();
finishConnect(key);
}
! public void onRead(IOEvent<Context> ioEvent) {
}
! public void onWrite(IOEvent<Context> ioEvent) {
}
};
***************
*** 446,452 ****
--- 447,466 ----
this.controller = controller;
}
+ public SelectableChannel getUnderlyingChannel() {
+ return datagramChannel;
}
+
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+ }