Package org.jredis.ri.alphazero.protocol

Source Code of org.jredis.ri.alphazero.protocol.ProtocolBase$StreamBufferRequest

/*
*   Copyright 2009-2010 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.protocol;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;

import org.jredis.ClientRuntimeException;
import org.jredis.NotSupportedException;
import org.jredis.ProviderException;
import org.jredis.protocol.Command;
import org.jredis.protocol.Protocol;
import org.jredis.protocol.Request;
import org.jredis.protocol.Response;
import org.jredis.protocol.ResponseStatus;
import org.jredis.ri.alphazero.support.Assert;
import org.jredis.ri.alphazero.support.Convert;
import org.jredis.ri.alphazero.support.Log;


/**
* [TODO: document me!]
*
* @author  Joubin (alphazero@sensesay.net)
* @version alpha.0, Apr 10, 2009
* @since   alpha.0
*
*/
public abstract class ProtocolBase implements Protocol {

  // ------------------------------------------------------------------------
  // Protocol Revision specific
  // ------------------------------------------------------------------------

  public static final byte[]   CRLF = {(byte) 13, (byte)10};
  public static final byte[]   SPACE = {(byte) 32};
  public static final int   CRLF_LEN = CRLF.length;
  public static final int   DELIMETER_LEN = SPACE.length;
  public static final byte  ERR_BYTE   = (byte) 45; // -
  public static final byte  OK_BYTE   = (byte) 43; // +
  public static final byte  COUNT_BYTE   = (byte) 42; // *
  public static final byte  SIZE_BYTE   = (byte) 36; // $
  public static final byte  NUM_BYTE   = (byte) 58; // :
  public static final byte  ASCII_ZERO  = (byte) 48; // 0
 
  // ------------------------------------------------------------------------
  // Protocol Revision specific consts
  // ------------------------------------------------------------------------
  protected ProtocolBase () {}
 
  // ------------------------------------------------------------------------
  // Interface: Protocol
  // ------------------------------------------------------------------------
 
  /* TODO: lets just forget about this multi-version nonsense. */ 
  @Override
  public boolean isCompatibleWithVersion(String version) {
    return version.equals("0.09");
  }
 
  public byte[] createRequestBuffer(Command cmd, byte[]...args) throws ProviderException, IllegalArgumentException {
    class Buffer {
      byte[] b = null;
      private int off = 0;
      Buffer(int size){
        b = new byte[size];
      }
      void write (byte[] d){
        final int dlen = d.length;
        System.arraycopy(d, 0, b, off, dlen);
        off+=dlen;
      }
      void write (byte d){
        b[off] = d;
        off++;
      }
      byte[] getBytes() {
        return b;
      }
    }
    Buffer buffer = null;
    byte[] cmdLenBytes = Convert.toBytes(cmd.bytes.length);
    byte[] lineCntBytes = Convert.toBytes(args.length+1);

    // calculate the buffer size
    int bsize = 1 + lineCntBytes.length + CRLF_LEN + 1 + cmdLenBytes.length + CRLF_LEN + cmd.bytes.length + CRLF_LEN;
    for(int i=0;i<args.length; i++){
      byte[] argLenBytes = Convert.toBytes(Assert.notNull(args[i], i, ProviderException.class).length);
      int _bsize = 1 + argLenBytes.length + CRLF_LEN + args[i].length + CRLF_LEN;
      bsize += _bsize;
    }
   
    buffer = new Buffer(bsize);
        buffer.write(COUNT_BYTE);      // 1
        buffer.write(lineCntBytes);    // lineCntBytes.length()
        buffer.write(CRLF);        // CRLF.lengt
        buffer.write(SIZE_BYTE);    // 1
        buffer.write(cmdLenBytes);    // length
        buffer.write(CRLF);        // CRLF_LEN
        buffer.write(cmd.bytes);    //
        buffer.write(CRLF);
       
    switch (cmd.requestType) {

    case NO_ARG:
        break;
       
    // TODO: check w/ antirez if in fact nulls are now generally accepted
    // that is the only diff here.
    case BULK_SET:
      String errmsg = "Only MSET, MSETNX, LINSERT bulk commands are supported";
      Assert.isTrue(cmd == Command.MSET || cmd == Command.MSETNX || cmd == Command.LINSERT, errmsg, NotSupportedException.class);

      // THIS IS CLEARLY BROKEN ... SO MUCH FOR COMPREHSIVE TESTS ...
      buffer.write(COUNT_BYTE);
      buffer.write(lineCntBytes);
      buffer.write(CRLF);
      buffer.write(SIZE_BYTE);
      buffer.write(cmdLenBytes);
      buffer.write(CRLF);
      buffer.write(cmd.bytes);
      buffer.write(CRLF);
     
      for(int s=0; s<args.length; s++){
        buffer.write(SIZE_BYTE);
        if (args[s] != null) {
            buffer.write(Convert.toBytes(args[s].length));
            buffer.write(CRLF);
            buffer.write(args[s]);
            buffer.write(CRLF);
          } else {
          buffer.write(ASCII_ZERO);
          buffer.write(CRLF);
          buffer.write(CRLF);
          }
      }
      break;
   
    default:
      for(int i=0;i<args.length; i++){
        buffer.write(SIZE_BYTE);
        buffer.write(Convert.toBytes(Assert.notNull(args[i], i, ProviderException.class).length));
        buffer.write(CRLF);
        buffer.write(args[i]);
        buffer.write(CRLF);
      }
      break;
   
    }
    return buffer.getBytes();
  }

  /* (non-Javadoc)
   * @see org.jredis.connector.Protocol#createRequest(org.jredis.Command, byte[][])
   */
  @Override
  public Request createRequest(Command cmd, byte[]... args) throws ProviderException, IllegalArgumentException {
   
    ByteArrayOutputStream buffer = createRequestBufffer (cmd);

    try {
      byte[] cmdLenBytes = Convert.toBytes(cmd.bytes.length);
      byte[] lineCntBytes = Convert.toBytes(args.length+1);

            buffer.write(COUNT_BYTE);
            buffer.write(lineCntBytes);
            buffer.write(CRLF);
            buffer.write(SIZE_BYTE);
            buffer.write(cmdLenBytes);
            buffer.write(CRLF);
            buffer.write(cmd.bytes);
            buffer.write(CRLF);
           
      switch (cmd.requestType) {

      case NO_ARG:
          break;
         
      // TODO: check w/ antirez if in fact nulls are now generally accepted
      // that is the only diff here.
      case BULK_SET:
        String errmsg = "Only MSET, MSETNX, LINSERT bulk commands are supported";
        Assert.isTrue(cmd == Command.MSET || cmd == Command.MSETNX || cmd == Command.LINSERT, errmsg, NotSupportedException.class);

        // THIS IS CLEARLY BROKEN ... SO MUCH FOR COMPREHSIVE TESTS ...
        buffer.write(COUNT_BYTE);
        buffer.write(lineCntBytes);
        buffer.write(CRLF);
        buffer.write(SIZE_BYTE);
        buffer.write(cmdLenBytes);
        buffer.write(CRLF);
        buffer.write(cmd.bytes);
        buffer.write(CRLF);
       
        for(int s=0; s<args.length; s++){
          buffer.write(SIZE_BYTE);
          if (args[s] != null) {
              buffer.write(Convert.toBytes(args[s].length));
              buffer.write(CRLF);
              buffer.write(args[s]);
              buffer.write(CRLF);
            } else {
            buffer.write(ASCII_ZERO);
            buffer.write(CRLF);
            buffer.write(CRLF);
            }
        }
        break;
     
      default:
        for(int i=0;i<args.length; i++){
          buffer.write(SIZE_BYTE);
          buffer.write(Convert.toBytes(Assert.notNull(args[i], i, ProviderException.class).length));
          buffer.write(CRLF);
          buffer.write(args[i]);
          buffer.write(CRLF);
        }
        break;
     
      }
    }
    catch (IOException e) {
      throw new ProviderException("Problem writing to the buffer" + e.getLocalizedMessage(), e);
    }
    return createRequest(buffer);
  }
 
  /* (non-Javadoc)
   * @see org.jredis.connector.Protocol#createResponse(org.jredis.Command)
   */
  @Override
  public Response createResponse(Command cmd) throws ProviderException, ClientRuntimeException {

    Response response = null;
    switch (cmd.responseType){
    case BOOLEAN:
      response = createBooleanResponse(cmd);
      break;
    case BULK:
      response = createBulkResponse (cmd);
      break;
    case MULTI_BULK:
      response = createMultiBulkResponse (cmd);
      break;
    case NUMBER:
      response = createNumberResponse (cmd);
      break;
    case STATUS:
      response = createStatusResponse (cmd);
      break;
    case STRING:
      response = createStringResponse (cmd);
      break;
    case VIRTUAL:
      response = new VirtualResponse(ResponseStatus.STATUS_CIAO);
      break;
    case NOP:
      response = new VirtualResponse(ResponseStatus.STATUS_OK); // TODO: needs more thinking ..
      break;
    case QUEUED:
    case RESULT_SET:
      throw new NotSupportedException(String.format("ResponseType %s not yet supported", cmd.requestType.name()));
   
    }

    return response;
 
  }


  // ------------------------------------------------------------------------
  // Extension Points
  // ------------------------------------------------------------------------
 
  protected abstract ByteArrayOutputStream createRequestBufffer(Command cmd);
  protected abstract Request createRequest (ByteArrayOutputStream buffer);
  protected abstract Response createMultiBulkResponse(Command cmd) ;
  protected abstract Response createBulkResponse(Command cmd) ;
  protected abstract Response createNumberResponse(Command cmd /*, boolean bigNum*/) ;
  protected abstract Response createBooleanResponse(Command cmd) ;
  protected abstract Response createStringResponse(Command cmd) ;
  protected abstract Response createStatusResponse(Command cmd);

 
  // ========================================================================
  // Inner Types
  // ========================================================================
 
  /**
   * SimpleRequest implements the required {@link Request#read(InputStream)}
   * using a (likely) shared data buffer.  It is not thread safe and can only
   * be used by connections that serialized request processing through a single
   * requesting thread.
   * <p>
   * Specifically, if an instance of this class is obtained and not immediately
   * used (by calling read) before the user has obtained another instance of the
   * same, data corruption is guaranteed.
   *
   * @author  Joubin Houshyar (alphazero@sensesay.net)
   * @version alpha.0, 04/02/09
   * @since   alpha.0
   *
   */
  public static class StreamBufferRequest implements Request {

    /**  */
    ByteArrayOutputStream buffer;
    /**
     * @param buffer
     */
    public StreamBufferRequest (ByteArrayOutputStream  buffer) {
      this.buffer = buffer;
    }
    public void reset (ByteArrayOutputStream  buffer) {
      this.buffer = buffer;
    }
    /* (non-Javadoc)
     * @see com.alphazero.jredis.connector.Message#read(java.io.InputStream)
     */
    @Override
    public void read(InputStream in) throws ClientRuntimeException, ProviderException {
      throw new ProviderException("Request.read is not supported by this class! [Apr 2, 2009]");
    }

    /**
     * Writes the entire content of the message to the output stream and flushes it.
     *
     * @param out the stream to write the Request message to.
     */
    @Override
    public void write(OutputStream out) throws ClientRuntimeException, ProviderException {
      try {
        // you would expect these to throw exceptions if the socket has been reset
        // but they don't. 
        buffer.writeTo(out);
        out.flush();
      }
      catch (SocketException e){
        Log.error("StreamBufferRequest.write(): SocketException on write: " + e.getLocalizedMessage());
        throw new ClientRuntimeException ("socket exception", e);
      }
      catch (IOException e) {
        Log.error("StreamBufferRequest.write(): IOException on write: " + e.getLocalizedMessage());
        throw new ClientRuntimeException ("stream io exception", e);
      }
    }
  }
}
TOP

Related Classes of org.jredis.ri.alphazero.protocol.ProtocolBase$StreamBufferRequest

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.