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

org.voovan.tools.buffer.RingDirectBuffer Maven / Gradle / Ivy

There is a newer version: 4.3.8
Show newest version
package org.voovan.tools.buffer;

import org.voovan.tools.*;
import org.voovan.tools.exception.LargerThanMaxSizeException;
import org.voovan.tools.exception.MemoryReleasedException;
import org.voovan.tools.log.Logger;
import sun.misc.Unsafe;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeoutException;

/**
 * 环形缓冲区
 *
 * @author: helyho
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class RingDirectBuffer {
    private static int BYTEBUFFERCHANNEL_MAX_SIZE = TProperties.getInt("framework", "ByteBufferChannelMaxSize", 1024*1024*2);
	private int maxSize = BYTEBUFFERCHANNEL_MAX_SIZE==0 ? 1024*1024*2 : BYTEBUFFERCHANNEL_MAX_SIZE;

	private static Unsafe unsafe = TUnsafe.getUnsafe();
    private ByteBuffer byteBuffer;
    private long address = 0;
    private int readPositon = 0;
    private int writePositon = 0;
    private int capacity;

    /**
     * 使用默认容量构造一个环形缓冲区
     */
    public RingDirectBuffer(){
        this(TByteBuffer.DEFAULT_BYTE_BUFFER_SIZE);
    }

    /**
     * 使用指定容量构造一个环形缓冲区
     * @param capacity 分配的容量
     */
    public RingDirectBuffer(int capacity){
    	this(TByteBuffer.allocateDirect(capacity));
    }

    /**
     * 使用指定容量构造一个环形缓冲区
     * @param byteBuffer ByteBuffer 对象
     */
    public RingDirectBuffer(ByteBuffer byteBuffer){
        if(byteBuffer.hasArray()){
            throw new UnsupportedOperationException();
        }

        this.capacity = byteBuffer.capacity();
        this.byteBuffer = byteBuffer;
        try {
            this.address = TByteBuffer.getAddress(byteBuffer);
        } catch (ReflectiveOperationException e) {
            Logger.error("Get bytebuffer address error.");
        }
    }


	/**
	 * 获得环形缓冲区的基地址
	 * @return 环形缓冲区的基地址
	 */
	public long getAddress() {
		return address;
	}

	/**
	 * 获得读指针位置
	 * @return 读指针位置
	 */
	public int getReadPositon() {
		return readPositon;
	}

	/**
	 * 获得写指针位置
	 * @return 写指针位置
	 */
	public int getWritePositon() {
		return writePositon;
	}

	/**
	 * 获得容量
	 * @return 容量
	 */
	public int getCapacity() {
		return capacity;
	}

	/**
	 * 读指针跳过特定的偏移量
	 * @param offset 偏移量
	 * @return true: 成功, false: 失败
	 */
	public boolean skip(int offset){
		checkRelease();

		if(remaining() < offset || offset < 0){
			return false;
		}

		readPositon = ( readPositon + offset ) % capacity;
		return true;
	}

	/**
	 * 缓冲区空判断
	 * @return true: 缓冲区无可用数据, false: 缓冲区有可用数据
	 */
	public Boolean isEmpty() {
		return readPositon == writePositon;
	}

	/**
	 * 缓冲区满判断
	 * @return true: 缓冲区已满, false: 缓冲区未满
	 */
	public Boolean isFull() {
		return (writePositon + 1) % capacity == readPositon;
	}

	/**
	 * 清理缓冲区
	 */
	public void clear() {
		checkRelease();

		this.readPositon = 0;
		this.writePositon = 0;
	}

	/**
	 * 获得基于索引位置的数据
	 * @param offset 偏移量
	 * @return byte 数据
	 */
	public byte get(int offset) {
		checkRelease();

		if(offset < remaining()) {
			int realOffset = (readPositon + offset) % capacity;
			return unsafe.getByte(address + realOffset);
		} else {
			throw new IndexOutOfBoundsException();
		}
	}

	/**
	 * 读取所有缓冲区的数据
	 *      不影响读写位置
	 * @param byteBuffer ByteBuffer 对象
	 * @return 读取数据大小
	 */
	public int get(ByteBuffer byteBuffer) {
		checkRelease();

		int size = byteBuffer.remaining();
		if(size > remaining()){
			size = remaining();
		}

		for(int i=0;i remaining()){
			length = remaining();
		}

		for(int i=offset;i 0){
			write(byteBuffer.get());
			size++;
			writeSize--;
		}

		return size;
	}

	/**
	 * 缓冲区可读数据量
	 * @return 缓冲区可用数据量
	 */
	public int remaining() {
		checkRelease();

		if(writePositon == readPositon){
			return 0;
		} else if(writePositon < readPositon){
			return capacity - readPositon + writePositon;
		} else {
			return writePositon - readPositon;
		}
	}

	/**
	 * 缓冲区可写空间
	 * @return 缓冲区可写空间
	 */
	public int avaliable() {
		checkRelease();

		return capacity - remaining() - 1;
	}

	/**
	 * 读取一个 byte
	 * @return byte 数据
	 */
	public byte read() {
		checkRelease();

		if (isEmpty()) {
			throw new BufferUnderflowException();
		}
		byte result = unsafe.getByte(address + readPositon);
		readPositon = (readPositon + 1) % capacity;

		if(isEmpty() && readPositon!=0){
			clear();
		}
		return result;
	}

	/**
	 * 读取缓冲区的数据
	 * @param byteBuffer ByteBuffer 对象
	 * @return 读取数据大小
	 */
	public int read(ByteBuffer byteBuffer) {
		checkRelease();

		int size = byteBuffer.remaining();
		if(size > remaining()){
			size = remaining();
		}

		for(int i=0;i remaining()){
			length = remaining();
		}

		for(int i=offset;i{

            if(remaining() >= length){
                return false;
            } else {
                supplier.run();
                return remaining() < length;
            }
        });
	}


	/**
	 * 从头部开始判断是否收到期望的数据
	 * @param mark  期望出现的数据
	 * @param timeout 超时时间,单位: 毫秒
	 * @param supplier 每次等待数据所做的操作
	 * @return true: 具备期望长度的数据, false: 等待数据超时
	 */
	public boolean waitData(byte[] mark, int timeout, Runnable supplier){
		checkRelease();

        return TEnv.wait(timeout, ()->{
            if(indexOf(mark) != -1) {
                return false;
            } else {
                supplier.run();
                return indexOf(mark) == -1;
            }
        });
	}

	/**
	 * 读取一行
	 * @return 字符串
	 */
	public String readLine() {
		checkRelease();

		if(remaining() == 0){
			return null;
		}

		String lineStr = null;

		int index = indexOf("\n".getBytes());

		int size = -1;

		if (index >= 0) {
			if(readPositon > index) {
				size = capacity - readPositon + index;
			} else {
				size = index - readPositon;
			}

			size++;


		}

		if(remaining()>0 && index==-1){
			size = remaining();
		}

		byte[] temp = new byte[size];

		for(int i=0;i 0) {
				loadSize = length > bufferSize ? bufferSize : Long.valueOf(length).intValue();

				tempByteBuffer.limit(loadSize);

				this.read(tempByteBuffer);

				randomAccessFile.write(buffer, 0, loadSize);

				length = length - loadSize;

				tempByteBuffer.clear();
			}
		} catch (IOException e) {
			throw e;
		} finally {
			randomAccessFile.close();
		}

	}

	/**
	 * 测试是否被释放
	 */
	private void checkRelease(){
		if(isReleased()){
			throw new MemoryReleasedException("ByteBufferChannel is released.");
		}
	}

	public boolean isReleased(){
		if(address == 0 || byteBuffer == null){
			return true;
		}else{
			return false;
		}
	}

	/**
	 * 释放内存中的数据
	 */
	public synchronized void release(){
		address = 0;
		byteBuffer = null;
		TByteBuffer.release(byteBuffer);
	}

	/**
	 * 重新分配内存空间的大小
	 * @param dataSize  重新分配的空间大小
	 * @return true:成功, false:失败
	 * @throws LargerThanMaxSizeException 通道容量不足的一场
	 */
	public boolean tryExpansion(int dataSize) throws LargerThanMaxSizeException {
		checkRelease();

		if(dataSize > avaliable()) {
			getByteBuffer();

			int newCapacity = capacity + dataSize;

			//检查分配内存是否超过限额
			if (maxSize < dataSize) {
				throw new LargerThanMaxSizeException("Max size: " + maxSize + ", expect size: " + newCapacity);
			}


			if (TByteBuffer.reallocate(byteBuffer, newCapacity)) {
				this.capacity = newCapacity;
				resetAddress();
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public void resetAddress(){
		try {
			this.address = TByteBuffer.getAddress(byteBuffer);
		} catch (ReflectiveOperationException e) {
			Logger.error("Get bytebuffer address error.");
		}
	}

	@Override
	public String toString(){
		return "readPositon=" + readPositon+", writePositon="+writePositon+", capacity="+capacity+", remaining="+remaining()+", avaliable="+avaliable()+", address="+address;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy