Package com.starlight.intrepid

Source Code of com.starlight.intrepid.LargeTransferTest$ChannelReadThread

// Copyright (c) 2010 Rob Eden.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Intrepid nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.starlight.intrepid;

import com.starlight.intrepid.exception.ChannelRejectedException;
import junit.framework.TestCase;
import org.apache.mina.core.buffer.SimpleBufferAllocator;

import java.io.Serializable;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;


/**
*
*/
public class LargeTransferTest extends TestCase {
  private Intrepid client_instance = null;
  private Intrepid server_instance = null;


  @Override
  protected void tearDown() throws Exception {
    // Re-enable
    IntrepidTesting.setInterInstanceBridgeDisabled( false );

    if ( client_instance != null ) client_instance.close();
    if ( server_instance != null ) server_instance.close();
  }

  @Override
  protected void setUp() throws Exception {
    final SimpleBufferAllocator delegate = new SimpleBufferAllocator();
//    IoBuffer.setAllocator( new IoBufferAllocator() {
//      @Override
//      public IoBuffer allocate( int capacity, boolean direct ) {
//        System.out.println( "*** allocate: " + capacity + ", " + direct );
//        return delegate.allocate( capacity, direct );
//      }
//
//      @Override
//      public ByteBuffer allocateNioBuffer( int capacity, boolean direct ) {
//        System.out.println( "*** allocateNio: " + capacity + ", " + direct );
//        return delegate.allocateNioBuffer( capacity, direct );
//      }
//
//      @Override
//      public IoBuffer wrap( ByteBuffer nioBuffer ) {
//        System.out.println( "*** wrap: " + nioBuffer );
//        return delegate.wrap( nioBuffer );
//      }
//
//      @Override
//      public void dispose() {
//        new Throwable( "*** dispose" ).printStackTrace();
////        delegate.dispose();
//      }
//    } );
  }

  public void testLargeTransfer() throws Exception {
    byte[] data = new byte[ 1024 * 1024 * 16 ]// 16 M
    new Random().nextBytes( data );

    // Make sure we test the full stack. See comment on
    // "Intrepid.disable_inter_instance_bridge" for more info.
    IntrepidTesting.setInterInstanceBridgeDisabled( true );

    server_instance = Intrepid.create(
      new IntrepidSetup().vmidHint( "server" ).openServer() );
    Integer server_port = server_instance.getServerPort();
    assertNotNull( server_port );
    ServerImpl original_instance = new ServerImpl();
    server_instance.getLocalRegistry().bind( "server", original_instance );

    client_instance = Intrepid.create( new IntrepidSetup().vmidHint( "client" ) );

    // Connect to the server
    VMID server_vmid = client_instance.connect( InetAddress.getByName( "127.0.0.1" ),
      server_port.intValue(), null, null );
    assertNotNull( server_vmid );

    // Lookup the server object
    Registry server_registry = client_instance.getRemoteRegistry( server_vmid );
    Server server = ( Server ) server_registry.lookup( "server" );

    double total_bps = 0;
    for ( int i = 0; i < 5; i++ ) {
      long start = System.currentTimeMillis();
      byte[] data_copy = server.send( data, start );
      long transfer_time = System.currentTimeMillis() - start;
      double bps = ( ( data.length * 2 ) / ( double ) transfer_time ) * 1000.0;
      total_bps += bps;
      System.out.println( "Method round-trip time: " + transfer_time +
        "  - " + NumberFormat.getNumberInstance().format( bps ) + " Bps" );

      assertTrue( Arrays.equals( data, data_copy ) );
    }
    System.out.println( "Average Bps: " +
      NumberFormat.getNumberInstance().format( total_bps / 5.0 ) );
  }


  public void testStreamingLargeTransfer() throws Exception {
    byte[] data = new byte[ 1024 * 1024 * 16 ]// 16 M
    new Random().nextBytes( data );

    // Make sure we test the full stack. See comment on
    // "Intrepid.disable_inter_instance_bridge" for more info.
    IntrepidTesting.setInterInstanceBridgeDisabled( true );

    final int RUNS = 50;
    final CountDownLatch read_latch = new CountDownLatch( RUNS );
    final AtomicBoolean read_error_slot = new AtomicBoolean( false );
   
    server_instance = Intrepid.create(
      new IntrepidSetup().vmidHint( "server" ).openServer().channelAcceptor(
      new TestAcceptor( data, read_latch, read_error_slot ) ) );
    Integer server_port = server_instance.getServerPort();
    assertNotNull( server_port );
    ServerImpl original_instance = new ServerImpl();
    server_instance.getLocalRegistry().bind( "server", original_instance );

    client_instance = Intrepid.create( new IntrepidSetup().vmidHint( "client" ) );

    // Connect to the server
    VMID server_vmid = client_instance.connect( InetAddress.getByName( "127.0.0.1" ),
      server_port.intValue(), null, null );
    assertNotNull( server_vmid );

    double total_bps = 0;
    for( int i = 0; i < RUNS; i++ ) {
      ByteChannel channel = client_instance.createChannel( server_vmid, null );

      ByteBuffer write_buffer = ByteBuffer.allocate( 1 << 18 ); // 256KB
      long start = System.currentTimeMillis();
      int pos = 0;
      while( pos < data.length ) {
        write_buffer.put( data, pos,
          Math.min( write_buffer.remaining(), data.length - pos ) );
        pos += write_buffer.position();
        write_buffer.flip();

        channel.write( write_buffer );
        write_buffer.clear();
      }
      channel.close();
      long time = System.currentTimeMillis() - start;
      double bps = ( ( data.length * 2 ) / ( double ) time ) * 1000.0;
      total_bps += bps;
      System.out.println( "Client done writing in " + time + " ms: " +
        NumberFormat.getNumberInstance().format( bps ) + " Bps" );
     
      assertFalse( read_error_slot.get() );
    }
   
    long start = System.currentTimeMillis();
    read_latch.await();
    long time = System.currentTimeMillis() - start;
    assertTrue( "Waited too long for read_latch: " + time, time < 1000 );
   
    assertFalse( read_error_slot.get() );
   
    System.out.println( "Average Bps: " +
      NumberFormat.getNumberInstance().format( total_bps / ( double ) RUNS ) );
  }

  public void testConcurrentStreamingLargeTransfer() throws Exception {
    final byte[] data = new byte[ 1024 * 1024 * 16 ]// 16 M
    new Random().nextBytes( data );

    // Make sure we test the full stack. See comment on
    // "Intrepid.disable_inter_instance_bridge" for more info.
    IntrepidTesting.setInterInstanceBridgeDisabled( true );

    final int RUNS = 50;
    final CountDownLatch read_latch = new CountDownLatch( RUNS );
    final AtomicBoolean read_error_slot = new AtomicBoolean( false );

    server_instance = Intrepid.create(
      new IntrepidSetup().vmidHint( "server" ).openServer().channelAcceptor(
      new TestAcceptor( data, read_latch, read_error_slot ) ) );
    Integer server_port = server_instance.getServerPort();
    assertNotNull( server_port );
    ServerImpl original_instance = new ServerImpl();
    server_instance.getLocalRegistry().bind( "server", original_instance );

    client_instance = Intrepid.create( new IntrepidSetup().vmidHint( "client" ) );

    // Connect to the server
    final VMID server_vmid =
      client_instance.connect( InetAddress.getByName( "127.0.0.1" ),
      server_port.intValue(), null, null );
    assertNotNull( server_vmid );

    // Allow 10 streams at a time
    ExecutorService service = Executors.newFixedThreadPool( 10 );

    final CountDownLatch latch = new CountDownLatch( RUNS );
    final AtomicReference<Exception> exception_slot = new AtomicReference<Exception>();

    long start = System.currentTimeMillis();
    for( int i = 0; i < RUNS; i++ ) {
      final int thread_number = i;
      service.execute( new Runnable() {
        @Override
        public void run() {
          try {
            System.out.println( "Starting thread " + thread_number );
            ByteChannel channel =
              client_instance.createChannel( server_vmid, null );

            ByteBuffer write_buffer = ByteBuffer.allocate( 1 << 18 ); // 256KB
            long start = System.currentTimeMillis();
            int pos = 0;
            while( pos < data.length ) {
              write_buffer.put( data, pos,
                Math.min( write_buffer.remaining(), data.length - pos ) );
              pos += write_buffer.position();
              write_buffer.flip();

              channel.write( write_buffer );
              write_buffer.clear();
            }
            channel.close();
            long time = System.currentTimeMillis() - start;
            double bps = ( ( data.length * 2 ) / ( double ) time ) * 1000.0;
            System.out.println( "Client done writing in " + time + " ms: " +
              NumberFormat.getNumberInstance().format( bps ) + " Bps" );

            assertFalse( read_error_slot.get() );
          }
          catch( Exception ex ) {
            exception_slot.set( ex );
          }
          finally {
            latch.countDown();
            System.out.println( "Thread " + thread_number + " complete" );
          }
        }
      } );
    }

    //noinspection ThrowableResultOfMethodCallIgnored
    if ( exception_slot.get() != null ) throw exception_slot.get();

    System.out.println( "Waiting for completion..." );
    latch.await();
    System.out.println( "All threads completed." );

    double total_bps = ( data.length * RUNS ) /
      ( double ) TimeUnit.MILLISECONDS.toSeconds( System.currentTimeMillis() - start );

    start = System.currentTimeMillis();
    read_latch.await();
    long time = System.currentTimeMillis() - start;
    assertTrue( "Waited too long for read_latch: " + time, time < 1000 );

    assertFalse( read_error_slot.get() );

    System.out.println( "Average Bps: " +
      NumberFormat.getNumberInstance().format( total_bps / ( double ) RUNS ) );
  }


  public interface Server {
    public byte[] send( byte[] data, long send_time );
  }

  public class ServerImpl implements Server {
    @Override
    public byte[] send( byte[] data, long send_time ) {
      long transfer_time = System.currentTimeMillis() - send_time;

      double bps = ( data.length / ( double ) transfer_time ) * 1000.0;


      System.out.println( "Got data is length: " + data.length +
        "  - " + NumberFormat.getNumberInstance().format( bps ) + " Bps" );
      return data;
    }
  }


  public class TestAcceptor implements ChannelAcceptor {
    private final byte[] expected_data;
    private final CountDownLatch read_latch;
    private final AtomicBoolean read_error_slot;


    TestAcceptor( byte[] expected_data, CountDownLatch read_latch,
      AtomicBoolean read_error_slot ) {
     
      this.expected_data = expected_data;
      this.read_latch = read_latch;
      this.read_error_slot = read_error_slot;
    }

    @Override
    public void newChannel( ByteChannel channel, VMID source_vmid,
      Serializable attachment ) throws ChannelRejectedException {

      new ChannelReadThread( channel, expected_data, read_latch,
        read_error_slot ).start();
    }
  }


  public class ChannelReadThread extends Thread {
    private final ByteChannel channel;

    private final byte[] expected_data;
    private final CountDownLatch read_latch;
    private final AtomicBoolean read_error_slot;

    byte[] data;
    ByteBuffer read_buffer = ByteBuffer.allocate( 1 << 18 ); // 256KB

    ChannelReadThread( ByteChannel channel, byte[] expected_data,
      CountDownLatch read_latch, AtomicBoolean read_error_slot ) {
     
      this.channel = channel;
      this.expected_data = expected_data;
      this.read_latch = read_latch;
      this.read_error_slot = read_error_slot;
      this.data = new byte[ expected_data.length ];
    }

    @Override
    public void run() {
      try {
        long start = System.currentTimeMillis();

        int pos = 0;
        int read;
        while( ( read = channel.read( read_buffer ) ) != -1 ) {
          read_buffer.flip();

          assert read_buffer.remaining() == read :
            read_buffer.remaining() + " != " + pos;
          read_buffer.get( data, pos, read_buffer.remaining() );
          pos += read;
          read_buffer.clear();
        }

        assert pos == data.length;
        long time = System.currentTimeMillis() - start;

        double bps = ( data.length / ( double ) time ) * 1000.0;

        System.out.println( "Server read " + data.length + " bytes in " +
          time + ": " + NumberFormat.getNumberInstance().format( bps ) + " Bps" );

        if ( !Arrays.equals( expected_data, data ) ) {
          System.err.println( "******************Data mismatch******************" );
          read_error_slot.set( true );
        }
       
        read_latch.countDown();
      }
      catch( Exception ex ) {
        ex.printStackTrace();
      }
    }
  }
}
TOP

Related Classes of com.starlight.intrepid.LargeTransferTest$ChannelReadThread

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.