Package com.yahoo.omid.tso

Source Code of com.yahoo.omid.tso.ClientHandler

/**
* Copyright (c) 2011 Yahoo! Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/

package com.yahoo.omid.tso;

import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;

import com.yahoo.omid.client.SyncAbortCompleteCallback;
import com.yahoo.omid.client.SyncCommitCallback;
import com.yahoo.omid.client.SyncCommitQueryCallback;
import com.yahoo.omid.client.SyncCreateCallback;
import com.yahoo.omid.client.TSOClient;
import com.yahoo.omid.tso.messages.CommitResponse;
import com.yahoo.omid.tso.messages.TimestampResponse;

/**
* Example of ChannelHandler for the Transaction Client
*
* @author maysam
*
*/
public class ClientHandler extends TSOClient {

   private static final Log LOG = LogFactory.getLog(ClientHandler.class);

   /**
    * Maximum number of modified rows in each transaction
    */
   static final int MAX_ROW = 20;

   /**
    * The number of rows in database
    */
   static final int DB_SIZE = 20000000;

   private static final long PAUSE_LENGTH = 50; // in ms

   /**
    * Maximum number if outstanding message
    */
   private final int MAX_IN_FLIGHT;

   /**
    * Number of message to do
    */
   private final int nbMessage;

   /**
    * Current rank (decreasing, 0 is the end of the game)
    */
   private int curMessage;

   /**
    * number of outstanding commit requests
    */
   private int outstandingTransactions = 0;

   /**
    * Start date
    */
   private Date startDate = null;

   /**
    * Stop date
    */
   private Date stopDate = null;

   /**
    * Return value for the caller
    */
   final BlockingQueue<Boolean> answer = new LinkedBlockingQueue<Boolean>();

   private Committed committed = new Committed();
   private Set<Long> aborted = Collections.synchronizedSet(new HashSet<Long>(100000));

   /*
    * For statistial purposes
    */
   public ConcurrentHashMap<Long, Long> wallClockTime = new ConcurrentHashMap<Long, Long>();

   public long totalNanoTime = 0;
   public long totalTx = 0;
  
   private Channel channel;

   private float percentReads;

   /**
    * Method to wait for the final response
    *
    * @return success or not
    */
   public boolean waitForAll() {
      for (;;) {
         try {
            return answer.take();
         } catch (InterruptedException e) {
            // Ignore.
         }
      }
   }

   /**
    * Constructor
    *
    * @param nbMessage
    * @param inflight
    * @throws IOException
    */
   public ClientHandler(Configuration conf, int nbMessage, int inflight, boolean pauseClient,
         float percentReads) throws IOException {
      super(conf);
      if (nbMessage < 0) {
         throw new IllegalArgumentException("nbMessage: " + nbMessage);
      }
      this.MAX_IN_FLIGHT = inflight;
      this.nbMessage = nbMessage;
      this.curMessage = nbMessage;
      this.pauseClient = pauseClient;
      this.percentReads = percentReads;
   }

   /**
    * Starts the traffic
    */
   @Override
   public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
      super.channelConnected(ctx, e);
      startDate = new Date();
      channel = e.getChannel();
      outstandingTransactions = 0;
      startTransaction();
   }

   /**
    * If write of Commit Request was not possible before, just do it now
    */
   @Override
   public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
      startTransaction();
   }

   /**
    * When the channel is closed, print result
    */
   @Override
   public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
      super.channelClosed(ctx, e);
      stopDate = new Date();
      String MB = String.format("Memory Used: %8.3f MB", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime()
            .freeMemory()) / 1048576.0);
      String Mbs = String.format("%9.3f TPS",
            ((nbMessage - curMessage) * 1000 / (float) (stopDate.getTime() - (startDate != null ? startDate.getTime()
                  : 0))));
      System.out.println(MB + " " + Mbs);
   }

   /**
    * When a message is received, handle it based on its type
    * @throws IOException
    */
   @Override
   protected void processMessage(TSOMessage msg) {
      if (msg instanceof CommitResponse) {
         handle((CommitResponse) msg);
      } else if (msg instanceof TimestampResponse) {
         handle((TimestampResponse) msg);
      }
   }

   /**
    * Handle the TimestampResponse message
    */
   public void handle(TimestampResponse timestampResponse) {
      sendCommitRequest(timestampResponse.timestamp);
   }

   /**
    * Handle the CommitRequest message
    */
   private long lasttotalTx = 0;
   private long lasttotalNanoTime = 0;
   private long lastTimeout = System.currentTimeMillis();

   public void handle(CommitResponse msg) {
      // outstandingTransactions.decrementAndGet();
      outstandingTransactions--;
      long finishNanoTime = System.nanoTime();
      long startNanoTime = wallClockTime.remove(msg.startTimestamp);
      if (msg.committed) {
         totalNanoTime += (finishNanoTime - startNanoTime);
         totalTx++;
         long timeout = System.currentTimeMillis();
         // if (totalTx % 10000 == 0) {//print out
         if (timeout - lastTimeout > 60 * 1000) { // print out
            long difftx = totalTx - lasttotalTx;
            long difftime = totalNanoTime - lasttotalNanoTime;
            System.out.format(
                  " CLIENT: totalTx: %d totalNanoTime: %d microtime/tx: %4.3f tx/s %4.3f "
                        + "Size Com: %d Size Aborted: %d Memory Used: %8.3f KB TPS:  %9.3f \n",
                  difftx,
                  difftime,
                  (difftime / (double) difftx / 1000),
                  1000 * difftx / ((double) (timeout - lastTimeout)),
                  getSizeCom(),
                  getSizeAborted(),
//                  largestDeletedTimestamp - _decoder.lastStartTimestamp,
                  (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024.0,
                  ((nbMessage - curMessage) * 1000 / (float) (new Date().getTime() - (startDate != null ? startDate
                        .getTime() : 0))));
            lasttotalTx = totalTx;
            lasttotalNanoTime = totalNanoTime;
            lastTimeout = timeout;
         }
      } else {// aborted
         try {
            super.completeAbort(msg.startTimestamp, new SyncAbortCompleteCallback());
         } catch (IOException e) {
            LOG.error("Couldn't send abort", e);
         }
      }
      startTransaction();
   }

   private long getSizeCom() {
      return committed.getSize();
   }

   private long getSizeAborted() {
      return aborted.size() * 8 * 8;
   }

   private java.util.Random rnd;

   private boolean pauseClient;

   /**
    * Sends the CommitRequest message to the channel
    *
    * @param timestamp
    * @param channel
    */
   private void sendCommitRequest(final long timestamp) {
      if (!((channel.getInterestOps() & Channel.OP_WRITE) == 0))
         return;

      // initialize rnd if it is not yet
      if (rnd == null) {
         long seed = System.currentTimeMillis();
         seed *= channel.getId();// to make it channel dependent
         rnd = new java.util.Random(seed);
      }

      boolean readOnly = (rnd.nextFloat() * 100) < percentReads;

      int size = readOnly ? 0 : rnd.nextInt(MAX_ROW);
      final RowKey [] rows = new RowKey[size];
      for (byte i = 0; i < rows.length; i++) {
         long l = rnd.nextInt(DB_SIZE);
         byte[] b = new byte[8];
         for (int iii = 0; iii < 8; iii++) {
            b[7 - iii] = (byte) (l >>> (iii * 8));
         }
         byte[] tableId = new byte[8];
         rows[i] = new RowKey(b, tableId);
      }

      // send a query once in a while
      totalCommitRequestSent++;
      if (totalCommitRequestSent % QUERY_RATE == 0 && rows.length > 0) {
         long queryTimeStamp = rnd.nextInt(Math.abs((int) timestamp));
         try {
            isCommitted(timestamp, queryTimeStamp, new SyncCommitQueryCallback());
         } catch (IOException e) {
            LOG.error("Couldn't send commit query", e);
         }
      }

      executor.schedule(new Runnable() {
         @Override
         public void run() {
            // keep statistics
            wallClockTime.put(timestamp, System.nanoTime());

            try {
               commit(timestamp, rows, new SyncCommitCallback());
            } catch (IOException e) {
               LOG.error("Couldn't send commit", e);
               e.printStackTrace();
            }
         }
      }, pauseClient ? PAUSE_LENGTH : 0, TimeUnit.MILLISECONDS);

   }

   private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(20);

   private long totalCommitRequestSent;// just to keep the total number of
                                       // commitreqeusts sent
   private int QUERY_RATE = 100;// send a query after this number of commit
                                // requests

   /**
    * Start a new transaction
    *
    * @param channel
    * @throws IOException
    */
   private void startTransaction() {
      while (true) {// fill the pipe with as much as request you can
         if (!((channel.getInterestOps() & Channel.OP_WRITE) == 0))
            return;

         // if (outstandingTransactions.intValue() >= MAX_IN_FLIGHT)
         if (outstandingTransactions >= MAX_IN_FLIGHT)
            return;

         if (curMessage == 0) {
            LOG.warn("No more message");
            // wait for all outstanding msgs and then close the channel
            // if (outstandingTransactions.intValue() == 0) {
            if (outstandingTransactions == 0) {
               LOG.warn("Close channel");
               channel.close().addListener(new ChannelFutureListener() {
                  public void operationComplete(ChannelFuture future) {
                     answer.offer(true);
                  }
               });
            }
            return;
         }
         curMessage--;
//         TimestampRequest tr = new TimestampRequest();
         outstandingTransactions++;
         // outstandingTransactions.incrementAndGet();
//         Channels.write(channel, tr);
         try {
            super.getNewTimestamp(new SyncCreateCallback());
         } catch (IOException e) {
            LOG.error("Couldn't start transaction", e);
         }

         Thread.yield();
      }
   }
}
TOP

Related Classes of com.yahoo.omid.tso.ClientHandler

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.