Package com.barchart.udt.nio

Source Code of com.barchart.udt.nio.TestSelectorUDT$Handler

/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;

import static java.nio.channels.SelectionKey.*;
import static org.junit.Assert.*;
import static util.UnitHelp.*;

import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Arrays;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import util.TestAny;

/**
* basic single thread selector test
*/
public class TestSelectorUDT extends TestAny {

  @Before
  public void setUp() throws Exception {
  }

  @After
  public void tearDown() throws Exception {
  }

  protected static final int SIZE = 1460;

  protected static final int COUNT = 1000;

  final SelectorProvider provider = SelectorProviderUDT.DATAGRAM;

  volatile SelectionKey acceptKey;
  volatile SelectionKey serverKey;
  volatile SelectionKey clientKey;

  volatile ServerSocketChannel acceptChannel;
  volatile SocketChannel serverChannel;
  volatile SocketChannel clientChannel;

  volatile Selector selector;

  volatile SocketAddress acceptorAddress;
  volatile SocketAddress clientAddress;

  @Before
  public void init() throws Exception {

    selector = provider.openSelector();

    acceptChannel = provider.openServerSocketChannel();
    acceptChannel.configureBlocking(false);
    acceptorAddress = localSocketAddress();
    acceptChannel.socket().bind(acceptorAddress);

    acceptKey = acceptChannel.register(selector, OP_ACCEPT);

    clientChannel = provider.openSocketChannel();
    clientChannel.configureBlocking(false);
    clientAddress = localSocketAddress();
    clientChannel.socket().bind(clientAddress);

    clientKey = clientChannel.register(selector, OP_CONNECT);

    clientChannel.connect(acceptorAddress);

    log.info("test init");

  }

  @After
  public void done() throws Exception {

    log.info("test done");

  }

  volatile boolean isTestON = true;

  /** single pass state machine */
  /** FIXME */
  @Ignore
  @Test
  public void testSelect() {
    try {

      final Set<SelectionKey> selectedKeySet = selector.selectedKeys();

      selectLoop: while (isTestON) {

        final long timeout = 100;

        final int readyCount = selector.select(timeout);

        if (readyCount == 0) {
          continue selectLoop;
        }

        keyLoop: for (final SelectionKey key : selectedKeySet) {
          if (!key.isValid()) {
            continue keyLoop;
          }
          if (key.isReadable()) {
            doRead(key);
          }
          if (key.isWritable()) {
            doWrite(key);
          }
          if (key.isAcceptable()) {
            doAccept(key);
          }
          if (key.isConnectable()) {
            doConnect(key);
          }
        }

        selectedKeySet.clear();

      }

      log.info("before close");

      selector.close();

      log.info("after close");

    } catch (final Exception e) {
      fail(e.getMessage());
    }

  }

  interface Handler {

    void handleRead();

    void handleWrite();

  }

  final Queue<byte[]> serverQueue = new ConcurrentLinkedQueue<byte[]>();

  final Handler serverHandler = new Handler() {

    @Override
    public String toString() {
      return "serverHandler;" + " serverQueue:" + serverQueue.size()
          + " serverChannel:" + serverChannel;
    }

    final ByteBuffer readerBuffer = ByteBuffer.allocateDirect(SIZE);

    @Override
    public void handleRead() {
      try {
        while (true) {

          readerBuffer.clear();

          final int readSize = serverChannel.read(readerBuffer);

          if (readSize <= 0) {
            return;
          }

          assertEquals(readSize, SIZE);

          final byte[] array = new byte[readSize];

          readerBuffer.flip();
          readerBuffer.get(array);

          serverQueue.offer(array);

          serverKey.interestOps( //
              serverKey.interestOps() | OP_WRITE);

        }
      } catch (final Exception e) {
        fail(e.getMessage());
      }
    }

    final ByteBuffer writerBuffer = ByteBuffer.allocateDirect(SIZE);

    @Override
    public void handleWrite() {
      try {

        byte[] array;

        while ((array = serverQueue.poll()) != null) {

          writerBuffer.clear();
          writerBuffer.put(array);
          writerBuffer.flip();

          final int writeSize = serverChannel.write(writerBuffer);

          if (writeSize <= 0) {
            break;
          }

          assertEquals(writeSize, SIZE);

        }

        serverKey.interestOps(serverKey.interestOps() & ~OP_WRITE);

      } catch (final Exception e) {
        fail(e.getMessage());
      }
    }

  };

  final Queue<byte[]> clientQueue = new ConcurrentLinkedQueue<byte[]>();

  final Handler clientHandler = new Handler() {

    @Override
    public String toString() {
      return "clientHandler;" + "  clientQueue:" + clientQueue.size()
          + " clientChannel:" + clientChannel;
    }

    final ByteBuffer readerBuffer = ByteBuffer.allocateDirect(SIZE);

    final AtomicInteger readCount = new AtomicInteger(0);

    @Override
    public void handleRead() {
      try {
        while (true) {

          readerBuffer.clear();

          final int readSize = clientChannel.read(readerBuffer);

          if (readSize <= 0) {
            return;
          }

          assertEquals(readSize, SIZE);

          final byte[] arrayRead = new byte[readSize];

          readerBuffer.flip();
          readerBuffer.get(arrayRead);

          final byte[] arrayWritten = clientQueue.poll();

          assertNotNull(arrayWritten);
          assertTrue(Arrays.equals(arrayRead, arrayWritten));

          final int count = readCount.incrementAndGet();

          if (count == COUNT) {
            clientKey.interestOps( //
                clientKey.interestOps() & ~OP_READ);
            isTestON = false;
            log.info("client read done");
            return;
          }

        }
      } catch (final Exception e) {
        fail(e.getMessage());
      }
    }

    final ByteBuffer writerBuffer = ByteBuffer.allocateDirect(SIZE);

    final Random random = new Random();

    final AtomicInteger writeCount = new AtomicInteger(0);

    @Override
    public void handleWrite() {
      try {
        while (true) {

          final byte[] array = new byte[SIZE];

          random.nextBytes(array);

          writerBuffer.clear();
          writerBuffer.put(array);
          writerBuffer.flip();

          final int writeSize = clientChannel.write(writerBuffer);

          if (writeSize <= 0) {
            return;
          }

          assertEquals(writeSize, SIZE);

          clientQueue.offer(array);

          final int count = writeCount.incrementAndGet();

          if (count == COUNT) {
            clientKey.interestOps(//
                clientKey.interestOps() & ~OP_WRITE);

            log.info("client write done");

            return;
          }
        }
      } catch (final Exception e) {
        fail(e.getMessage());
      }
    }

  };

  private void doAccept(final SelectionKey key) {
    try {

      log.info("doAccept; key={}", key);

      assertEquals(key, acceptKey);
      assertEquals(acceptChannel, key.channel());

      assertNull(serverChannel);
      assertNull(serverKey);

      serverChannel = acceptChannel.accept();
      serverChannel.configureBlocking(false);

      serverKey = serverChannel.register(selector, OP_READ);
      serverKey.attach(serverHandler);

    } catch (final Exception e) {
      fail(e.getMessage());
    }
  }

  private void doConnect(final SelectionKey key) {
    try {

      log.info("doConnect; key={}", key);

      assertEquals(key, clientKey);
      assertEquals(clientChannel, key.channel());

      assertTrue(clientChannel.finishConnect());
      assertTrue(clientChannel.isConnected());

      clientKey.interestOps(OP_READ | OP_WRITE);
      clientKey.attach(clientHandler);

    } catch (final Exception e) {
      fail(e.getMessage());
    }

  }

  private void doRead(final SelectionKey key) {

    log.info("key:\n\t{}", key);

    final Object attachment = key.attachment();

    assertTrue(attachment instanceof Handler);

    final Handler handler = (Handler) attachment;

    handler.handleRead();

  }

  private void doWrite(final SelectionKey key) {

    log.info("key:\n\t{}", key);

    final Object attachment = key.attachment();

    assertTrue(attachment instanceof Handler);

    final Handler handler = (Handler) attachment;

    handler.handleWrite();

  }

  @Test(timeout = 3000)
  public void testWakeup() throws Exception {

    final SelectorProvider provider = SelectorProviderUDT.DATAGRAM;

    final Selector selector = provider.openSelector();

    final Thread thread = new Thread() {

      @Override
      public void run() {

        try {

          log.info("init");

          /** blocking */
          selector.select();

          log.info("done");

        } catch (final IOException e) {
          e.printStackTrace();
        }

      }

    };

    thread.start();

    Thread.sleep(300);

    selector.wakeup();

    thread.join();

  }
}
TOP

Related Classes of com.barchart.udt.nio.TestSelectorUDT$Handler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.