Package org.jgroups.tests

Source Code of org.jgroups.tests.StreamingStateTransferTest$GroupMember

package org.jgroups.tests;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.jgroups.Address;
import org.jgroups.BlockEvent;
import org.jgroups.Channel;
import org.jgroups.ExtendedReceiver;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.StreamingGetStateEvent;
import org.jgroups.StreamingSetStateEvent;
import org.jgroups.TimeoutException;
import org.jgroups.UnblockEvent;
import org.jgroups.View;
import org.jgroups.ViewId;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.util.Util;

/**
* Tests streaming state transfer for both pull and push mode of channel
* operations. Size of the transfer is configurable. Test runner should
* specify "pull" and "size" parameter as JVM parameters when running this
* test. If not specified default values are to use push mode and transfer
* size of 100 MB.
*
<p>
*  To specify pull mode and size transfer of 500 MB test runner should pass
*  JVM parameters:
<p>
*  -Dpull=true -Dsize=500
*
*
* @author Vladimir Blagojevic
* @version $Id$
*
*/
public class StreamingStateTransferTest extends TestCase{

  private final static String CHANNEL_PROPS="streaming-state-transfer.xml";
  private final static int INITIAL_NUMBER_OF_MEMBERS=5;
  private int runningTime = 1000*50; // 50 secs
  private Random r = new Random();
  private boolean usePullMode = false;
    private boolean useDisp = false;
  private int size = 100; //100MB
 
  private final static int MEGABYTE = 1048576;
 
 
  public StreamingStateTransferTest(String arg0) {
    super(arg0);
  }
 
  public void testTransfer() throws Exception
  {
    long start = System.currentTimeMillis();
    boolean running=true;
    List members=new ArrayList();     
   
    //first spawn and join
    for(int i =0;i<INITIAL_NUMBER_OF_MEMBERS;i++)
    {
      GroupMember member = new GroupMember(usePullMode,useDisp,size);     
      members.add(member);
      Thread t = new Thread(member);
      t.start();
      Util.sleep(getRandomDelayInSeconds(10,12)*1000);
    }
   
    for (; running;) {           
     
      //and then flip a coin
      if(r.nextBoolean())
      {
        Util.sleep(getRandomDelayInSeconds(10,12)*1000);
        GroupMember member = new GroupMember(usePullMode,useDisp,size);         
        members.add(member);       
        Thread t = new Thread(member);
        t.start();
      }
      else if(members.size()>1)
      {
        Util.sleep(getRandomDelayInSeconds(3,8)*1000);
        GroupMember unluckyBastard = (GroupMember) members.get(r.nextInt(members.size()));
        if(!unluckyBastard.isCoordinator())
        {
          members.remove(unluckyBastard);       
          unluckyBastard.stopRunning();         
        }
        else
        {
          System.out.println("Not killing coordinator ");
        }
      }       
      running =System.currentTimeMillis() - start <= runningTime;
      System.out.println("Running time " + ((System.currentTimeMillis()-start)/1000) + " secs");
    }
    System.out.println("Done");
  }
 
  protected int getRandomDelayInSeconds(int from,int to)
  {
    return from + r.nextInt(to-from);
  }

  protected void setUp() throws Exception {
   
    //NOTE use -Ddisp=true|false -Dpull=true|false -Dsize=int (size of transfer)
      
        String prop = System.getProperty("disp");
        if(prop!=null)
        {
            useDisp = prop.equalsIgnoreCase("true");
            System.out.println("Using parameter disp=" + useDisp);
        }
    prop = System.getProperty("pull");
    if(prop!=null)
    {
      usePullMode = prop.equalsIgnoreCase("true");
      System.out.println("Using parameter usePullMode=" + usePullMode);
    }
   
    prop = System.getProperty("size");
    if(prop!=null)
    {
      size = Integer.parseInt(System.getProperty("size"));
      System.out.println("Using parameter size=" + size);
    }
    super.setUp();
  }

  protected void tearDown() throws Exception {
    super.tearDown();   
  }
 
  public static Test suite() {     
        return new TestSuite(StreamingStateTransferTest.class);
  }
  
  public static void main(String[] args) {   
     String[] testCaseName={StreamingStateTransferTest.class.getName()};
       junit.textui.TestRunner.main(testCaseName);
  }
 
  private static class GroupMember implements Runnable,ExtendedReceiver{
    JChannel ch = null;   
    View currentView;   
    volatile boolean running = true;   
    private int stateSize; 
    private int bufferSize = 8*1024;
    private boolean usePullMode; 
    private Random ran = new Random();
        private boolean useDispacher;

    public GroupMember(boolean pullMode, boolean dispMode, int size) {
      setStateSize(size * MEGABYTE);
      setUsePullMode(pullMode);
      setUseDispatcher(dispMode);
      try {
        ch = new JChannel(CHANNEL_PROPS);
        ch.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
        ch.setOpt(Channel.AUTO_GETSTATE, Boolean.TRUE);
        ch.setOpt(Channel.BLOCK, Boolean.TRUE);
        if (useDispacher) {
          RpcDispatcher disp = new RpcDispatcher(ch, this, this, this);
        } else if (!usePullMode) {
          ch.setReceiver(this);
        }
        ch.connect("transfer");       
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
   
    public final void setUsePullMode(boolean usePullMode) {
      this.usePullMode = usePullMode;
    }
       
        public final void setUseDispatcher(boolean useDispacher) {
            this.useDispacher = useDispacher;
        }

    public String getAddress() {
      if(ch!=null && ch.isConnected())
      {
        return ch.getLocalAddress().toString();
      }
      return null;
    }

    public void stopRunning() {
      running=false
      System.out.println("Disconnect " + getAddress());
      if(ch!=null)ch.close();
   
   
    protected boolean isCoordinator() {
      if (ch == null)
        return false;
      Object local_addr = ch.getLocalAddress();
      if (local_addr == null)
        return false;
      View view = ch.getView();
      if (view == null)
        return false;
      ViewId vid = view.getVid();
      if (vid == null)
        return false;
      Object coord = vid.getCoordAddress();
      if (coord == null)
        return false;
      return local_addr.equals(coord);
    }

    public final void setStateSize(int stateSize) {
      this.stateSize = stateSize;
    }

    public void run() {
      Runnable r = new Runnable() {
        public void run() {
          try {
            if (ran.nextBoolean()) {
              ch.getState(null, 5000);
            } else {
              String randomStateId = Long.toString(Math.abs(ran.nextLong()), 36);
              ch.getState(null, randomStateId, 5000);
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      };
      if (usePullMode) { 
       
        //when BLOCK events are turned on, pbcast.FLUSH is used and we use pull channel mode
        //we have to getState on a separate thread. Why? Because joining member has to immediatelly
        //go into receive and fetch/respond to block event which is received as part of state transfer.
        new Thread(r).start();
      }
      else
      {
        r.run();
      }
      while (running) {
        Object msgReceived = null;
        try {         
          msgReceived = ch.receive(0);
                    if (msgReceived instanceof BlockEvent) {
                       this.block();
                       ch.blockOk();
                    } else if (msgReceived instanceof UnblockEvent) {
                       this.unblock();                          
                    }
          if (!running) {
            // I am not a group member anymore so
            // I will discard any transient message I
            // receive
          } else {
            if (msgReceived instanceof View) {             
            } else if (msgReceived instanceof StreamingGetStateEvent) {
              StreamingGetStateEvent evt = (StreamingGetStateEvent) msgReceived;
              if(evt.getStateId()!=null)
              {
                this.getState(evt.getStateId(),evt.getArg())
              }
              else
              {
                this.getState(evt.getArg());
              }
            } else if (msgReceived instanceof StreamingSetStateEvent) {
              StreamingSetStateEvent evt = (StreamingSetStateEvent) msgReceived;
              if(evt.getStateId()!=null)
              {
                this.setState(evt.getStateId(),evt.getArg());
              }
              else
              {
                this.setState(evt.getArg());
              }
            }
          }                   

        } catch (TimeoutException e) {         
        } catch (Exception e) {         
          ch.close();
          running = false;
        }     
      }         
    }
 
    public void getState(OutputStream ostream) {     
      InputStream stream = Thread.currentThread().getContextClassLoader()
          .getResourceAsStream("org/jgroups/JChannel.class");
      System.out.println(Thread.currentThread() + " at " + getAddress()
          + " is sending state of " + (stateSize / MEGABYTE) + " MB");
     
      int markSize = 1024*100; //100K should be enough
      byte buffer [] = new byte[bufferSize];
      int bytesRead=-1
      int size = stateSize;
      try {                             
        while(size>0)
        {
          stream.mark(markSize);
          bytesRead=stream.read(buffer);
          ostream.write(buffer);
          stream.reset();                 
          size = size-bytesRead;         
        }         
      } catch (IOException e) {       
        e.printStackTrace();
     
      finally
      {       
        try {
          ostream.flush();
          ostream.close();
        } catch (IOException e) {         
          e.printStackTrace();
        }       
      }
    }

    public void setState(InputStream istream) {
      int totalRead=0;
      byte buffer [] = new byte[bufferSize];
      int bytesRead=-1;
      long start = System.currentTimeMillis();
      try {
        while((bytesRead=istream.read(buffer))>=0)
        {         
          totalRead+=bytesRead;
        }               
      } catch (IOException e) {       
        e.printStackTrace();
      }
      finally
      {
        try {
          istream.close();
        } catch (IOException e) {         
          e.printStackTrace();
        }
      }
      long readingTime = System.currentTimeMillis()-start;
      System.out.println(Thread.currentThread() + " at " + getAddress()
          + " read state of " + (totalRead / MEGABYTE) + " MB in "
          + readingTime + " msec");           
    }

    public void receive(Message msg) {   
    }

    public void setState(byte[] state) {     
    }

    public void viewAccepted(View new_view) {     
    }

    public void suspect(Address suspected_mbr) {   
    }

    public void block() { 
           // System.out.println("Block at " + ch.getLocalAddress());
    }

        public void unblock() {
           // System.out.println("Unblock at " + ch.getLocalAddress());
        }

        public byte[] getState() {
      return null;
    }
   
    public byte[] getState(String state_id) {   
      return null;
    }

    public void setState(String state_id, byte[] state) {           
    }

    public void getState(String state_id, OutputStream ostream) {
      System.out.println("Writing partial streaming state transfer for " + state_id);
      getState(ostream);
    }

    public void setState(String state_id, InputStream istream) {
      System.out.println("Reading partial streaming state transfer for " + state_id);
      setState(istream);     
    }   
  }
}
TOP

Related Classes of org.jgroups.tests.StreamingStateTransferTest$GroupMember

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.