All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.generallycloud.baseio.component.AioSocketChannel Maven / Gradle / Ivy

/*
 * Copyright 2015-2017 GenerallyCloud.com
 *  
 * 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 com.generallycloud.baseio.component;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.nio.channels.AsynchronousSocketChannel;

import com.generallycloud.baseio.ClosedChannelException;
import com.generallycloud.baseio.buffer.ByteBuf;
import com.generallycloud.baseio.buffer.UnpooledByteBufAllocator;
import com.generallycloud.baseio.common.CloseUtil;
import com.generallycloud.baseio.common.Logger;
import com.generallycloud.baseio.common.LoggerFactory;
import com.generallycloud.baseio.common.ReleaseUtil;
import com.generallycloud.baseio.protocol.ChannelWriteFuture;

public class AioSocketChannel extends AbstractSocketChannel {

	private AsynchronousSocketChannel		channel;
	private AioSocketChannelContext		context;
	private ReadCompletionHandler			readCompletionHandler;
	private WriteCompletionHandler		writeCompletionHandler;
	private ByteBuf					readCache;
	private CachedAioThread 				aioThread;

	private static final Logger			logger			= LoggerFactory
			.getLogger(AioSocketChannel.class);

	// FIXME 改进network wake 机制
	// FIXME network weak check
	public AioSocketChannel(CachedAioThread aioThread, AsynchronousSocketChannel channel) {
		super(aioThread);
		this.channel = channel;
		this.readCache = UnpooledByteBufAllocator.getHeapInstance().allocate(4096);
		this.context = aioThread.getChannelContext();
		this.readCompletionHandler = aioThread.getReadCompletionHandler();
		this.writeCompletionHandler = aioThread.getWriteCompletionHandler();
		this.aioThread = aioThread;
	}

	@Override
	public AioSocketChannelContext getContext() {
		return context;
	}
	
	@Override
	public  T getOption(SocketOption name) throws IOException {
		return channel.getOption(name);
	}

	@Override
	public  void setOption(SocketOption name, T value) throws IOException {
		channel.setOption(name, value);
	}

	@Override
	protected void doFlush(ChannelWriteFuture future) {
		flush(false);
	}
	
	@Override
	protected InetSocketAddress getRemoteSocketAddress0() throws IOException {
		return (InetSocketAddress) channel.getRemoteAddress();
	}

	@Override
	protected InetSocketAddress getLocalSocketAddress0() throws IOException {
		return (InetSocketAddress) channel.getLocalAddress();
	}
	
	private volatile boolean flushing;

	private void flush(boolean forceFlushing) {

		try {

			if (!forceFlushing && flushing) {
				return;
			}

			if (write_future == null) {
				write_future = write_futures.poll();
			}

			if (write_future == null) {
				flushing = false;
				return;
			}
			
			if (!isOpened()) {
				fireClosed(write_future, new ClosedChannelException("closed"));
				return;
			}

			flushing = true;

			write_future.write(this);

		} catch (IOException e) {

			fireClosed(write_future, e);
		}
	}

	private void fireClosed(ChannelWriteFuture future, IOException e) {

		if (future == null) {
			return;
		}

		future.onException(getSession(), e);
	}

	// FIXME 这里有问题
	@Override
	protected void physicalClose() {

		closeSSL();

		// 最后一轮 //FIXME once

		this.flush(false);

		this.opened = false;

		ReleaseUtil.release(readFuture);
		ReleaseUtil.release(sslReadFuture);

		this.releaseWriteFutures();

		try {
			channel.shutdownOutput();
		} catch (IOException e) {
			logger.info(e.getMessage(), e);
		}

		try {
			channel.shutdownInput();
		} catch (IOException e) {
			logger.info(e.getMessage(), e);
		}

		CloseUtil.close(channel);
		
		fireClosed();

		closeConnector();
	}

	public void read(ByteBuf cache) {
		channel.read(cache.clear().nioBuffer(), this, readCompletionHandler);
	}

	public void write(ByteBuf buf) {
		channel.write(buf.getNioBuffer(), this, writeCompletionHandler);
	}
	
	@Override
	public void close() throws IOException {

		synchronized (getCloseLock()) {
			
			if (!isOpened()) {
				return;
			}
			
			this.opened = false;
			
			physicalClose();
		}
		
	}
	
	// FIXME __hebing
	public void writeCallback(Integer length) {

		synchronized (getCloseLock()) {
			
			ChannelWriteFuture write_future = this.write_future;

			write_future.getByteBuf().reverse();

			if (!write_future.isCompleted()) {
				flush(true);
				return;
			}

			writeFutureLength.getAndAdd(-write_future.getBinaryLength());

			write_future.onSuccess(session);

			write_future = null;

			flush(true);
		}

	}

	public ByteBuf getReadCache() {
		return readCache;
	}
	
	@Override
	protected SocketChannelThreadContext getSocketChannelThreadContext() {
		return aioThread;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy