charlie hunt wrote:
> 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 ?
+1
>
> What do others think ?
The design is really good :-) I agree about the addition of process and
postProcess on the SelectionKeyHandler.
>
> 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.
Yes that will help understanding what is happening.
>
> 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 ?
I would vote for a "explanation meeting" just to learn about how this is
working :-) I would invite the Ericsson folks as I'm sure they gonna
like this feature.
>
> Additional thoughts anyone ?
Good work!
-- Jeanfrancois
>
> 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
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net