Code example for SelectionKey

Methods: SelectionKey.interestOps, interestOps, selector

0
        lock.lock();
        try { 
            // 满足以下两个条件时,切换到基于事件的写操作。 
            // 1.当前key对写事件不该兴趣。 
            // 2.write0()返回false。 
            if ((processKey.interestOps() & SelectionKey.OP_WRITE) == 0 && !write0()) {
                enableWrite(); 
            } 
        } finally { 
            lock.unlock();
        } 
    } 
 
    @Override 
    public void writeByEvent() throws IOException { 
        if (isClosed.get()) {
            return; 
        } 
        final ReentrantLock lock = this.writeLock;
        lock.lock();
        try { 
            // 满足以下两个条件时,切换到基于队列的写操作。 
            // 1.write0()返回true。 
            // 2.发送队列的buffer为空。 
            if (write0() && writeQueue.size() == 0) {
                disableWrite(); 
            } 
        } finally { 
            lock.unlock();
        } 
    } 
 
    /** 
     * 打开读事件 
     */ 
    public void enableRead() { 
        final Lock lock = this.keyLock;
        lock.lock();
        try { 
            SelectionKey key = this.processKey;
            key.interestOps(key.interestOps() | SelectionKey.OP_READ);
        } finally { 
            lock.unlock();
        } 
        processKey.selector().wakeup();
    } 
 
    /** 
     * 关闭读事件 
     */ 
    public void disableRead() { 
        final Lock lock = this.keyLock;
        lock.lock();
        try { 
            SelectionKey key = this.processKey;
            key.interestOps(key.interestOps() & OP_NOT_READ);
        } finally { 
            lock.unlock();
        } 
    } 
 
    /** 
     * 检查WriteBuffer容量,不够则写出当前缓存块并申请新的缓存块。 
     */ 
    public ByteBuffer checkWriteBuffer(ByteBuffer buffer, int capacity) {
        if (capacity > buffer.remaining()) {
            write(buffer);
            return processor.getBufferPool().allocate();
        } else { 
            return buffer;
        } 
    } 
 
    /** 
     * 把数据写到给定的缓存中,如果满了则提交当前缓存并申请新的缓存。 
     */ 
    public ByteBuffer writeToBuffer(byte[] src, ByteBuffer buffer) {
        int offset = 0;
        int length = src.length;
        int remaining = buffer.remaining();
        while (length > 0) {
            if (remaining >= length) {
                buffer.put(src, offset, length);
                break; 
            } else { 
                buffer.put(src, offset, remaining);
                write(buffer);
                buffer = processor.getBufferPool().allocate();
                offset += remaining;
                length -= remaining;
                remaining = buffer.remaining();
                continue; 
            } 
        } 
        return buffer;
    } 
 
    @Override 
    public boolean close() { 
        if (isClosed.get()) {
            return false; 
        } else { 
            if (closeSocket()) { 
                return isClosed.compareAndSet(false, true);
            } else { 
                return false; 
            } 
        } 
    } 
 
    public boolean isClosed() { 
        return isClosed.get();
    } 
 
    /** 
     * 由Processor调用的空闲检查 
     */ 
    protected abstract void idleCheck(); 
 
    /** 
     * 清理遗留资源 
     */ 
    protected void cleanup() { 
        BufferPool pool = processor.getBufferPool();
        ByteBuffer buffer = null;
 
        // 回收接收缓存 
        buffer = this.readBuffer;
        if (buffer != null) {
            this.readBuffer = null;
            pool.recycle(buffer);
        } 
 
        // 回收发送缓存 
        while ((buffer = writeQueue.poll()) != null) {
            pool.recycle(buffer);
        } 
    } 
 
    /** 
     * 获取数据包长度,默认是MySQL数据包,其他数据包重载此方法。 
     */ 
    protected int getPacketLength(ByteBuffer buffer, int offset) {
        if (buffer.position() < offset + packetHeaderSize) {
            return -1; 
        } else { 
            int length = buffer.get(offset) & 0xff;
            length |= (buffer.get(++offset) & 0xff) << 8;
            length |= (buffer.get(++offset) & 0xff) << 16;
            return length + packetHeaderSize;
        } 
    } 
 
    /** 
     * 检查ReadBuffer容量,不够则扩展当前缓存,直到最大值。 
     */ 
    private ByteBuffer checkReadBuffer(ByteBuffer buffer, int offset, int position) {
        // 当偏移量为0时需要扩容,否则移动数据至偏移量为0的位置。 
        if (offset == 0) {
            if (buffer.capacity() >= maxPacketSize) {
                throw new IllegalArgumentException("Packet size over the limit.");
            } 
            int size = buffer.capacity() << 1;
            size = (size > maxPacketSize) ? maxPacketSize : size;
            ByteBuffer newBuffer = ByteBuffer.allocate(size);
            buffer.position(offset);
            newBuffer.put(buffer);
            readBuffer = newBuffer;
            // 回收扩容前的缓存块 
            processor.getBufferPool().recycle(buffer);
            return newBuffer;
        } else { 
            buffer.position(offset);
            buffer.compact();
            readBufferOffset = 0;
            return buffer;
        } 
    } 
 
    private boolean write0() throws IOException { 
        // 检查是否有遗留数据未写出 
        ByteBuffer buffer = writeQueue.attachment();
        if (buffer != null) {
            int written = channel.write(buffer);
            if (written > 0) {
                netOutBytes += written;
                processor.addNetOutBytes(written);
            } 
            lastWriteTime = TimeUtil.currentTimeMillis();
            if (buffer.hasRemaining()) {
                writeAttempts++;
                return false; 
            } else { 
                writeQueue.attach(null);
                processor.getBufferPool().recycle(buffer);
            } 
        } 
        // 写出发送队列中的数据块 
        if ((buffer = writeQueue.poll()) != null) {
            // 如果是一块未使用过的buffer,则执行关闭连接。 
            if (buffer.position() == 0) {
                processor.getBufferPool().recycle(buffer);
                close(); 
                return true; 
            } 
            buffer.flip();
            int written = channel.write(buffer);
            if (written > 0) {
                netOutBytes += written;
                processor.addNetOutBytes(written);
            } 
            lastWriteTime = TimeUtil.currentTimeMillis();
            if (buffer.hasRemaining()) {
                writeQueue.attach(buffer);
                writeAttempts++;
                return false; 
            } else { 
                processor.getBufferPool().recycle(buffer);
            } 
        } 
        return true; 
    } 
 
    /** 
     * 打开写事件 
     */ 
    private void enableWrite() { 
        final Lock lock = this.keyLock;
        lock.lock();
        try { 
            SelectionKey key = this.processKey;
            key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
        } finally { 
            lock.unlock();
        } 
        processKey.selector().wakeup();
    } 
 
    /** 
     * 关闭写事件 
     */