From what I'm seeing / reading I like what I am seeing.
But, I feel I should ask others on this list if we should consider a
"concept review" of the changes / additions for our next Project Grizzly
meeting ?
What do others think ?
I'm thinking it might be useful to have a sequence diagram for inbound
and outbound connection caching. Perhaps a sequence diagram for
configuring as you've described and a sequence diagram showing how
connections are re-used.
But, since you've already had the connection management / cache code
integrated and tested in a project outside grizzly, a "concept review"
may not be needed and be a little over kill ?
Additional thoughts anyone ?
charlie ...
Oleksiy Stashok wrote:
> 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;
> + }
> +
> + }
>
>
> ------------------------------------------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>
--
Charlie Hunt
Java Performance Engineer
630.285.7708 x47708 (Internal)
<http://java.sun.com/docs/performance/>