Package org.jredis.ri.alphazero.wip

Source Code of org.jredis.ri.alphazero.wip.AsynchConnection$Pending

/*
*   Copyright 2009 Joubin Houshyar
*
*   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.
*/

package org.jredis.ri.alphazero.wip;

//import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import org.jredis.ClientRuntimeException;
import org.jredis.ProviderException;
import org.jredis.protocol.Command;
import org.jredis.protocol.Response;
import org.jredis.protocol.Response.Type;
import org.jredis.ri.alphazero.protocol.ProtocolBase;
import org.jredis.ri.alphazero.support.Convert;
import org.jredis.ri.alphazero.support.FastBufferedInputStream;
import org.jredis.ri.alphazero.support.Log;



public class AsynchConnection {
  public static void main(String[] args) throws Exception {
    AsynchConnection temp = new AsynchConnection();
   
    String host = "localhost";
    temp.doConnect (host);
   
    temp.test();
   
//    temp.doClose();
  }
  private void test() throws Exception {
    System.out.println("Hi!");

    startRequesters(100, 10000, true);
   
    boolean throttle = false;
    int cnt = 0;
    while (throttle) {
      cnt++;
//      pingReq();
//      pingReq();
//      pingReq();
      pingReq().completion.await();
//      incrReqSync ("counter").completion.await();
      incrReqSync ("counter");
//      getReqSynch("foo").completion.await();
      getReqSynch("foo").completion.await();
//      Thread.currentThread().yield();
//      getReq("counter");
    }
    keepWorking = false;
    System.out.println("bye!");
  }
 
  public void startRequesters(int threads, final int reqCnt, final boolean waitForCompletion) throws InterruptedException{
    // run 30 simultanuous threads
//    int threads = 1;
    final int counters[] = new int[threads];
    Thread[] workers = new Thread[threads];
    for(int t=0; t<threads; t++){
      final int idx = t;
//      final BlockingDeque<Pending> pending = new LinkedBlockingDeque<Pending>();
      workers[t] = new Thread(new Runnable() {
        int id = idx;
//        @Override
                public void run () {
          String counterId = "counter<" + this.hashCode() + ">:" + System.currentTimeMillis();
//          while(true){
          int last = 0;
          Pending pendingRequest = null;
          for(int i=0; i<reqCnt; i++){
            try {
//              pendingRequest = pingReq();
              pendingRequest = incrReqSync(counterId);
//              pendingRequest = getReqSynch("foo");
              if(waitForCompletion)
                pendingRequest.completion.await();
            }
            catch (Exception e) { e.printStackTrace(); }
          }
          try {
            if(!waitForCompletion)
              pendingRequest.completion.await();
            int lastValue = pendingRequest.intValue;
//            String value = DefaultCodec.toStr(pendingRequest.bulkData);
            System.out.format("%d\n", lastValue);
                    }
                    catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                    }
        }
      }, "requester_" + t);
    }
    for(int i=0; i<threads; i++){
      System.out.format("starting %d\n", i);
      workers[i].start();
    }
   
    for(int i=0; i<threads; i++)
      workers[i].join();
   
    System.out.println("all done with requesting threads ...");
   
  }
  // ----------------------------------------------------------------------------------------------
  // HACK Request Processing
  // ----------------------------------------------------------------------------------------------

  private void smembersReq(String key) throws Exception {
    serviceRequest(Command.SMEMBERS, key);
  }
  private Pending getReqSynch(String key) throws Exception {
    return serviceRequest(Command.GET, key);
  }
 
  private void authReq(String key) throws Exception {
    serviceRequest(Command.AUTH, key);
  }
 
  private Pending pingReq() throws Exception {
    return serviceRequest(Command.PING, "");
  }
 
  private int incrReq(String key) throws Exception {
    // note that this is wrong since its not really waiting completion
    return serviceRequest(Command.INCR, key).intValue;
  }

  private Pending incrReqSync(String key) throws Exception {
    return serviceRequest(Command.INCR, key);
  }

  // ----------------------------------------------------------------------------------------------
  // HACK RequestHandler
  // ----------------------------------------------------------------------------------------------

//  Semaphore service = new Semaphore(1);
  final Object lock = new Object();
  boolean keepWorking = true;

//  ByteArrayOutputStream bout = new ByteArrayOutputStream();
  private Pending serviceRequest (Command cmd, String key) throws IOException, InterruptedException{

//    bout.reset();
////    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
//    bout.write(cmd.code.getBytes());
//    bout.write((byte)32);
//    bout.write(key.getBytes());
//    bout.write(CRLF);
//    byte[] data =  bout.toByteArray();
   
    byte[] b_cmd = cmd.bytes;
    byte[] b_key = key.getBytes();
    byte[] data = new byte[b_cmd.length + b_key.length + CRLF.length + 1];
    System.arraycopy(b_cmd, 0, data, 0, b_cmd.length);
    data[b_cmd.length] = (byte)32;
    System.arraycopy(b_key, 0, data, b_cmd.length+1, b_key.length);
    data[b_cmd.length + 1 + b_key.length] = CRLF[0];
    data[b_cmd.length + 1 + b_key.length+1] = CRLF[1];
   
    Pending request = new Pending(cmd, key);
    request._data = data;

    // -- begin synch block
//    service.acquire();
    synchronized (lock) { // seems to have higher peaks, but is not as even as a semaphore but it seems to be faster
      out.write(data);
      out.flush();
      pendingQueue.add(request);
        }
//    service.release();
    // -- END synch block

    return request;
  }
  /************************************************************************************************
   **                                   Multi-Threaded Request Handler                          
   * @throws InterruptedException **
   ************************************************************************************************/
 
  // ----------------------------------------------------------------------------------------------
  // Threaded workers
  // ----------------------------------------------------------------------------------------------
 
  private Runnable getResponseHandler (final Queue<Pending> pendingQueue) {
    return new Runnable () {
      public void run () {
        try {
          processPendingRequests (pendingQueue, in);
        }
        catch (IOException e) {
          e.printStackTrace();
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    };
  }
 
//  private Runnable getRequestHandler (final Queue<Pending> requests, final Queue<Pending> pendingQueue){
//    return new Runnable(){
//      public void run() {
//        while(true){
//          Pending request = null;
//          if((request = requests.poll()) != null){
//            try {
////              System.out.format("=> %d\n", request._data.length);
//                          out.write(request._data);
//              out.flush();
//              request._data = null;
//              pendingQueue.add(request);
////              System.out.format("<=Q %d\n", pendingQueue.size());
////              System.out.println (".");
//                        }
//                        catch (IOException e) {
//                          // TODO Auto-generated catch block
//                          e.printStackTrace();
//                        }
//          }
//          else {
//            Thread.yield();
//          }
//        }
//      }
//    };
//  }
  // ----------------------------------------------------------------------------------------------
  // HACK Connection
  // ----------------------------------------------------------------------------------------------

  private InetAddress      address = null;
  private InetSocketAddress   socketAddress;
  private int         port = 6379;
  private Socket        socket;
 
  private void doClose() throws IOException {
    socket.close();
  }
  private void doConnect(String host) {
    try {
      initializeConnection (host);
      initializeComponents ();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  private void initializeComponents() {
//    Runnable reader = getReader(in, inqueue);
//    new Thread(reader, "input-reader").start();
   
//    Runnable handler = getResponseHandler(inqueue, pendingQueue);
   
//    Runnable writer = getRequestHandler(requestQueue, pendingQueue);
//    new Thread(writer, "request-writer").start();
   
    Runnable handler = getResponseHandler(pendingQueue);
    new Thread(handler, "response-handler").start();
  }
 
  private void initializeConnection (String host) throws IOException {
    address = InetAddress.getByName(host);
    socket = new Socket ();
    socket.setKeepAlive (true);
    socket.setPerformancePreferences(0, 2, 1);
    socketAddress = new InetSocketAddress(address, port);
    socket.connect(socketAddress);
   
    initializeStreams(socket);
  }
 
  // ----------------------------------------------------------------------------------------------
  // I/O Streams
  // ----------------------------------------------------------------------------------------------
  private InputStream        in;
  private OutputStream      out;
 
  private void initializeStreams (Socket aSocket) throws IOException {
//    out = new BufferedOutputStream (aSocket.getOutputStream());
    out = aSocket.getOutputStream();
//    in = new BufferedInputStream (aSocket.getInputStream(), BUFF_SIZE);
    in = socket.getInputStream();
  }
 
 
  // ----------------------------------------------------------------------------------------------
  // *** Globals ***
  // ----------------------------------------------------------------------------------------------

  /** Global Buffer Size -- all buffers, streams, and databuffers should be aligned on this */
  int       BUFF_SIZE = 1024 * 24;
 
  /* -- CONTROL */
  boolean    keep_reading = true;
  boolean   keep_processing = true;
 
  // ----------------------------------------------------------------------------------------------
  // Request Processing Queues and Classes
  // ----------------------------------------------------------------------------------------------

  /** queue: FRESH DATA BLOCKS */
//  LinkedBlockingDeque<DataBlock>   inqueue = new LinkedBlockingDeque<DataBlock>();
//  LinkedBlockingDeque<byte[]>   inqueue = new LinkedBlockingDeque<byte[]>();
 
  /** queue: PENDING REQUESTS  */
//  LinkedBlockingDeque<Pending>   pendingQueue = new LinkedBlockingDeque<Pending>();
  Queue<Pending>   pendingQueue = new ConcurrentLinkedQueue<Pending>();
  Queue<Pending>   requestQueue = new ConcurrentLinkedQueue<Pending>();

  // ----------------------------------------------------------------------------------------------
  // HACK - Specialized Queue Classes
  // ----------------------------------------------------------------------------------------------
 
  /**
   * TODO: Pending needs to wrap all possible commands, not just CMD + key type.
   * important elements are the latches and the status and response.
   */
  public static final class Pending {
    public byte[] _data;
    final public String id;
    public CountDownLatch completion = new CountDownLatch(1);
    public String  key;
    public Command  cmd;
    public final long request_time;
    private long  process_time;
    public Object  response;
    public boolean isError = false;
    public String  status = null;
    public int  intValue;
    public byte[] bulkData;
    public List<byte[]> multiBulkData;
    public Pending (Command cmd, String key){
      this.cmd = cmd; this.key = key;
      request_time = System.currentTimeMillis();
      id = this.hashCode() + "@" + request_time;
    }
    public void setResponse(Object response){
      this.response = response;
      this.process_time = System.currentTimeMillis() - request_time;
    }
    public long getProcessTime() { return process_time; }
  }
 
  private void processPendingRequests (
      Queue<Pending>   _pendingQueue,
      InputStream  inStream
    )
    throws
      IOException,
      InterruptedException
  {
   
//    BlockingDequeDataSource datasource = new BlockingDequeDataSource(_dataQueue);
//    InputStreamDataSource datasource = new InputStreamDataSource(inStream, BUFF_SIZE);
//    DataSourceInputStream in = new DataSourceInputStream(datasource, BUFF_SIZE);
    FastBufferedInputStream in = new FastBufferedInputStream(inStream, BUFF_SIZE);
   
    Response.Type   responseType = null;
    Pending     pending = null;
    long  mark=System.currentTimeMillis();
    long   delta=0;
    int    cnt = 0;
    int    errcnt = 0;
    int    gate = 100000;
    while (keepWorking){  // <<< some master flag is needed here
//      try {
//        if(_pendingQueue.size() > 200) {
//          System.out.format("pendingProcessor: pending queue size is %d\n", _pendingQueue.size());
//        }
//        pending = _pendingQueue.take(); // this is using Deque semantics
//        try {
        if((pending = _pendingQueue.poll()) == null) {
//          System.out.format("<=Q %d\n", _pendingQueue.size());
          Thread.yield();
        }
        else {
//          System.out.format("<=proc: %s\n", pending.cmd.name());
          switch (pending.cmd) {
          case PING:
          case AUTH:
            responseType = Type.Status;
            break;
          case GET:
            responseType = Type.Bulk;
            break;
          case INCR:
            responseType = Type.Value;
            break;
          case SMEMBERS:
            responseType = Type.MultiBulk;
            break;
          default:
            System.out.format("processIncomingData() - Pending Processer => don't know cmd %s \n", pending.cmd);
            continue;
          }
          try {
            switch(responseType){
            case Status:
              getStatusResponse(pending, in);
              break;
            case Value:
              getValueResponse(pending, in);
              break;
            case Bulk:
              getBulkResponse (pending, in);
              break;
            case MultiBulk:
              getMultiBulkResponse (pending, in);
              break;
            }
            pending.process_time = System.currentTimeMillis();
          }
          catch (IOException e) {
            Log.error("<" + Thread.currentThread().getName() + "> processing response" + e.getMessage());
          }
          pending.completion.countDown();
          cnt++;
          if(cnt == gate){
            delta = System.currentTimeMillis() - mark;
            float rate = (cnt * 1000)/delta;
            Log.log("");
            Log.log("<" + Thread.currentThread().getName() + "> processPendingRequests() -- REPORT:");
            Log.log("<" + Thread.currentThread().getName() + "> throughput %6.2f /sec | %6d reqs | %5d msecs [errors: %d]", rate, cnt, delta, errcnt);
            Log.log("<" + Thread.currentThread().getName() + "> last request processed: %s", pending.id);
            mark = System.currentTimeMillis();
            cnt=0;
            errcnt=0;
          }
        }
     
//        switch (pending.cmd) {
//        case PING:
//        case AUTH:
//          responseType = Type.Status;
//          break;
//        case GET:
//          responseType = Type.Bulk;
//          break;
//        case INCR:
//          responseType = Type.Value;
//          break;
//        case SMEMBERS:
//          responseType = Type.MultiBulk;
//          break;
//        default:
//          System.out.format("processIncomingData() - Pending Processer => don't know cmd %s \n", pending.cmd);
//          continue;
//        }
//      }
//      catch (InterruptedException e) {
//        Log.error("<" + Thread.currentThread().getName() + "> removing from pending queue" + e.getMessage());
//      }
     
//      try {
//        switch(responseType){
//        case Status:
//          getStatusResponse(pending, in);
//          break;
//        case Value:
//          getValueResponse(pending, in);
//          break;
//        case Bulk:
//          getBulkResponse (pending, in);
//          break;
//        case MultiBulk:
//          getMultiBulkResponse (pending, in);
//          break;
//        }
//        pending.process_time = System.currentTimeMillis();
//      }
//      catch (InterruptedException e) {
//        Log.error("<" + Thread.currentThread().getName() + "> processing response" + e.getMessage());
//      }
//      catch (IOException e) {
//        Log.error("<" + Thread.currentThread().getName() + "> processing response" + e.getMessage());
//      }
//      catch (ProviderException e) {
//        Log.error("<" + Thread.currentThread().getName() + "> processing response" + e.getMessage());
//        errcnt++;
//      }
//      pending.completion.countDown();
//      cnt++;
//      if(cnt == gate){
//        delta = System.currentTimeMillis() - mark;
//        float rate = (cnt * 1000)/delta;
//        Log.log("");
//        Log.log("<" + Thread.currentThread().getName() + "> processPendingRequests() -- REPORT:");
//        Log.log("<" + Thread.currentThread().getName() + "> throughput %6.2f /sec | %6d reqs | %5d msecs [errors: %d]", rate, cnt, delta, errcnt);
//        Log.log("<" + Thread.currentThread().getName() + "> last request processed: %s", pending.id);
//        mark = System.currentTimeMillis();
//        cnt=0;
//        errcnt=0;
//      }
//      System.out.format("Request %s %s processed in %d msecs\n", pending.cmd, pending.key, pending.getProcessTime());
    }
  }
 
  /* -------------------------------------------------------------------- */
  /* RESPONSE PROTOCOL STREAM PROCESSING  -- REPLACE SYNCH PROTOCOL STUFF */
  /* -------------------------------------------------------------------- */
 
  /**
     * @param pending
     * @param in2
     */
  private byte[] lineBuffer = new byte[128];
  private int    lineBufferOffset = 0;
 
    /**
     * Reads a single CRLF terminated line to lineBuffer.  lineBufferOffset will point to the next writable byte in lineBuffer.
     * @param in
     * @throws IOException
     */
    private void readLine (InputStream in) throws IOException {
      lineBufferOffset = 0;
      try {
        int c = -1;
        while((c = in.read(lineBuffer, lineBufferOffset, 1)) != -1){
        lineBufferOffset += c;
        if(lineBufferOffset > 2 && lineBuffer[lineBufferOffset-2]==CRLF[0] && lineBuffer[lineBufferOffset-1]==CRLF[1]){
          break// we're done
        }
        if(lineBuffer.length-lineBufferOffset == 0) {
          byte[] newbuff = new byte[lineBuffer.length * 2];
          System.arraycopy(lineBuffer, 0, newbuff, 0, lineBuffer.length);
          lineBuffer = newbuff;
        }
        }
      }
      catch (IOException e){
        e.printStackTrace();
        throw e;
      }
    }
    public final byte[] readBulkData (InputStream in, int length)
    throws IOException, RuntimeException
    {
      byte[] data = new byte[length]; // TODO: optimize me
      byte[] term = new byte[CRLF.length];

      int readcnt = -1;
      int offset = 0;

      while(offset < length){
        if((readcnt = in.read (data, offset, length-offset)) ==-1 ) throw new ClientRuntimeException("IO - read returned -1 -- problem");
        offset += readcnt;
      }
      if((readcnt = in.read (term, 0, CRLF.length)) != CRLF.length) {
        throw new RuntimeException ("Only read " + readcnt + " bytes for CRLF!");
      }
      return data;
    }
   
    /**
     * @param pending
     * @param in
     * @throws IOException
     */
    private void getStatusResponse (Pending pending, InputStream in) throws IOException {
      readLine (in);
      byte code = lineBuffer[0];
    if(code != ProtocolBase.OK_BYTE && code != ProtocolBase.ERR_BYTE) {
      throw new ProviderException ("Got [ " + (char)code + " | "+code+" ] when expecing either - or +  pending.status: " + pending.status);
    }
      pending.isError = code == ProtocolBase.ERR_BYTE;
      pending.status = new String(lineBuffer, 1, lineBufferOffset - 3);
    }

    private void getValueResponse (Pending pending, InputStream in) throws IOException {
      readLine (in);
      byte code = lineBuffer[0];
    if(code != ProtocolBase.NUM_BYTE && code != ProtocolBase.ERR_BYTE) {
      throw new ProviderException ("Got [ " + (char)code + " | "+code+" ] when expecing either - or :  pending.status: " + pending.status);
    }
      if((pending.isError = (code == ProtocolBase.ERR_BYTE)) != true){
        // flavor switch goes here
        pending.intValue = Convert.toInt(lineBuffer, 1, lineBufferOffset - 3);
      }
      else {
        pending.status = new String(lineBuffer, 1, lineBufferOffset - 3);
      }
    }

  private void getBulkResponse(Pending pending, InputStream in) throws IOException {
    readLine (in);
      byte code = lineBuffer[0];
    if(code != ProtocolBase.SIZE_BYTE && code != ProtocolBase.ERR_BYTE) {
      throw new ProviderException ("Got [ " + (char)code + " | "+code+" ] when expecing either - or $  pending.status: " + pending.status);
    }
    pending.isError = (code == ProtocolBase.ERR_BYTE);
    byte[] data = new byte[0];
      if(!pending.isError){
        int   length = Convert.toInt(lineBuffer, 1, lineBufferOffset - 3);
        if(length > 0) {
          data = readBulkData(in, length);
          pending.bulkData = data;
        }
      }
      else {
        pending.status = new String(lineBuffer, 1, lineBufferOffset - 3);
      }
  }
 
  private void getMultiBulkResponse(Pending pending, InputStream in) {
    List<byte[]>  multibulk = null;
    throw new RuntimeException("NOT IMPLEMENTED!");
  }
  // ----------------------------------------------------------------------------------------------
  // Response Type Handlers --
  // ----------------------------------------------------------------------------------------------


  // ----------------------------------------------------------------------------------------------
  // Response Data Protocol -- should be utility on byte[], Stream, or DataBuffer by now ..
  // ----------------------------------------------------------------------------------------------
  static final
  byte[]     CRLF = {(byte)13, (byte)10};
 
 
TOP

Related Classes of org.jredis.ri.alphazero.wip.AsynchConnection$Pending

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.