/** * * Copyright 2016-2016 spccold * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package sailfish.remoting.channel; import io.netty.bootstrap.Bootstrap; import io.netty.channel.EventLoopGroup; import io.netty.util.concurrent.EventExecutorGroup; import sailfish.remoting.Address; import sailfish.remoting.Tracer; import sailfish.remoting.configuration.NegotiateConfig; import sailfish.remoting.exceptions.SailfishException; import sailfish.remoting.handler.MsgHandler; import sailfish.remoting.protocol.Protocol; /** * @author spccold * @version $Id: MultiConnectionsExchangeChannelGroup.java, v 0.1 2016年11月22日 下午4:01:53 spccold Exp * $ */ public abstract class MultiConnectionsExchangeChannelGroup extends AbstractConfigurableExchangeChannelGroup { private final ExchangeChannel[] children; private final ExchangeChannel[] deadChildren; private final ExchangeChannelChooserFactory.ExchangeChannelChooser chooser; private final MsgHandler<Protocol> msgHandler; private final Tracer tracer; protected MultiConnectionsExchangeChannelGroup(Tracer tracer, MsgHandler<Protocol> msgHandler, Address address, short connections, int connectTimeout, int reconnectInterval, byte idleTimeout, byte maxIdleTimeOut, boolean lazy, boolean reverseIndex, NegotiateConfig config, ExchangeChannelGroup parentGroup, EventLoopGroup loopGroup, EventExecutorGroup executorGroup) throws SailfishException { this.tracer = tracer; this.msgHandler = msgHandler; children = new ExchangeChannel[connections]; deadChildren = new ExchangeChannel[connections]; if (null == config) { config = new NegotiateConfig(idleTimeout, maxIdleTimeOut, id(), ChannelType.readwrite.code(), (short) connections, (short) connections, (short) 0, reverseIndex); } Bootstrap bootstrap = null; for (short i = 0; i < connections; i++) { boolean success = false; final NegotiateConfig deepCopy = config.deepCopy().index(i); parentGroup = (null == parentGroup ? this : parentGroup); bootstrap = configureBoostrap(address, connectTimeout, deepCopy, parentGroup, loopGroup, executorGroup); try { children[i] = newChild(parentGroup, bootstrap, reconnectInterval, lazy, deepCopy.isRead()); success = true; } catch (SailfishException cause) { throw cause; } finally { if (!success) { close(Integer.MAX_VALUE); } } } chooser = DefaultExchangeChannelChooserFactory.INSTANCE.newChooser(children, deadChildren); } @Override public ExchangeChannel next() throws SailfishException { return chooser.next(); } /** * Return the number of {@link ExchangeChannel} this implementation uses. This number is the * maps 1:1 to the connections it use. */ public final int channelOCount() { return children.length; } public void close(int timeout) { if (this.isClosed()) { return; } synchronized (this) { if (this.isClosed()) { return; } this.closed = true; for (int i = 0; i < children.length; i++) { deadChildren[i] = null; if (null != children[i]) { children[i].close(timeout); } } } } @Override public boolean isAvailable() { if (this.isClosed()) { return false; } if (children.length == 1) {// one connection check return (null != children[0] && children[0].isAvailable()); } // can hit most of the time if (deadChildren[0] == null || deadChildren[0].isAvailable()) { return true; } for (int i = 1; i < children.length; i++) { if (deadChildren[i] == null || deadChildren[i].isAvailable()) { return true; } } return false; } @Override public MsgHandler<Protocol> getMsgHander() { return msgHandler; } @Override public Tracer getTracer() { return tracer; } /** * Create a new {@link ExchangeChannel} which will later then accessible via the {@link #next()} * method. */ protected abstract ExchangeChannel newChild(ExchangeChannelGroup parent, Bootstrap bootstrap, int reconnectInterval, boolean lazy, boolean readChannel) throws SailfishException; }