dev@grizzly.java.net

Re: ConnectionManagement/Cache integration

From: charlie hunt <charlie.hunt_at_sun.com>
Date: Fri, 25 May 2007 15:42:48 -0500

I'll add to next week's Grizzly meeting agenda.

Alexey: Does this sound ok to you?

thanks,

charlie ...


Jeanfrancois Arcand wrote:
>
>
> 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
>
> ---------------------------------------------------------------------
> 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/>