Package org.commoncrawl.rpc

Source Code of org.commoncrawl.rpc.BinaryProtocol

/**
* Copyright 2008 - CommonCrawl Foundation
*
* CommonCrawl licenses this file to you 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.commoncrawl.rpc;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableUtils;
import org.commoncrawl.util.shared.FlexBuffer;
import org.commoncrawl.util.shared.TextBytes;

public final class BinaryProtocol {

  public static final int  RAW_PROTOCOL_VERSION           = 1;

  public static final int  FIELD_ID_ENCODING_MODE_UNKNOWN = 0;
  public static final int  FIELD_ID_ENCODING_MODE_SHORT   = 1;
  public static final int  FIELD_ID_ENCODING_MODE_VINT    = 2;

  public static int        DEFAULT_PROTOCOL_ENCODING_MODE = FIELD_ID_ENCODING_MODE_VINT;

  private int              _currentMode;
  private static final int DEFAULT_MODE_STACK_CAPACITY    = 20;
  int                      _currentModeIdx                = -1;
  int                      _modeStack[]                   = new int[DEFAULT_MODE_STACK_CAPACITY];
  int                      _nestingLevel                  = 0;

  public BinaryProtocol() {
    pushFieldIdEncodingMode(FIELD_ID_ENCODING_MODE_UNKNOWN);
  }

  public int popFieldIdEncodingMode() {
    _currentMode = _modeStack[--_currentModeIdx];
    return _currentMode;
  }

  public void pushFieldIdEncodingMode(int mode) {
    if (_currentModeIdx + 1 == _modeStack.length) {
      int temp[] = new int[_modeStack.length * 2];
      System.arraycopy(_modeStack, 0, temp, 0, _currentModeIdx + 1);
      _modeStack = temp;
    }
    _modeStack[++_currentModeIdx] = mode;
    _currentMode = mode;
  }

  public int getFieldIdEncodingMode() {
    return _currentMode;
  }

  // start encoding fields
  public void beginFields(DataOutput out) throws IOException {
    // use default encoding type...
    pushFieldIdEncodingMode(DEFAULT_PROTOCOL_ENCODING_MODE);

    // if nesting level == 0 && encoding mode is new encoding mode
    if (_nestingLevel++ == 0 && _currentMode == FIELD_ID_ENCODING_MODE_VINT) {
      // write out protocol version
      out.writeByte(RAW_PROTOCOL_VERSION);
    }
  }

  // @Override
  public void beginField(DataOutput out, String fieldName, int fieldId)
      throws IOException {
    if (_currentMode == FIELD_ID_ENCODING_MODE_UNKNOWN) {
      throw new IOException("Unknown Field Id Encoding Mode!");
    }
    if (_currentMode == FIELD_ID_ENCODING_MODE_SHORT)
      out.writeShort(fieldId);
    else
      WritableUtils.writeVInt(out, fieldId);
  }

  // @Override
  public void endFields(DataOutput out) throws IOException {
    if (_currentMode == FIELD_ID_ENCODING_MODE_UNKNOWN) {
      throw new IOException("Unknown Field Id Encoding Mode!");
    }
    if (_currentMode == FIELD_ID_ENCODING_MODE_SHORT)
      out.writeShort(-1);
    else
      WritableUtils.writeVInt(out, -1);

    // ok pop encoding mode
    popFieldIdEncodingMode();
    // reduce nesting level
    _nestingLevel--;
  }

  // @Override
  public boolean readBool(DataInput in) throws IOException {
    return in.readBoolean();
  }

  // @Override
  public void readFlexBuffer(DataInput in,FlexBuffer buffer) throws IOException {
    int length = in.readInt();
    // set buffer's count to zero first ...
    buffer.setCount(0);
    if (length != 0) {
      // now reinit count to proper length ...
      // this prevents the buffer from copying old data to newly
      // allocated buffer if capacity < count
      buffer.setCount(length);
      in.readFully(buffer.get(),buffer.getOffset(),buffer.getCount());
    }
  }

  // @Override
  public byte readByte(DataInput in) throws IOException {
    return in.readByte();
  }

  // @Override
  public double readDouble(DataInput in) throws IOException {
    return in.readDouble();
  }

  // @Override
  public int readFieldId(DataInput in) throws IOException {

    int fieldIdOut = -1;

    // read first byte no matter what
    byte firstByte = in.readByte();
    // if mode is not VINT MODE
    if (_currentMode != FIELD_ID_ENCODING_MODE_VINT) {
      // ok if first byte is zero, then this is the old short encoding style ..
      if (_currentMode == FIELD_ID_ENCODING_MODE_SHORT
          || (firstByte == 0 || firstByte == -1)) {
        if (_currentMode == FIELD_ID_ENCODING_MODE_UNKNOWN) {
          // increment nesting level ...
          _nestingLevel++;
          // set mode
          pushFieldIdEncodingMode(FIELD_ID_ENCODING_MODE_SHORT);
        }
        // return second byte
        fieldIdOut = (int) ((((int) firstByte << 8)) | (in.readByte() & 0xff));
      } else if (_currentMode == FIELD_ID_ENCODING_MODE_UNKNOWN) {

        if (_nestingLevel++ == 0) {
          // skip version byte
          firstByte = in.readByte();
        }
        // shift to vint encoding mode ...
        pushFieldIdEncodingMode(FIELD_ID_ENCODING_MODE_VINT);
      }
    }

    if (_currentMode == FIELD_ID_ENCODING_MODE_VINT) {
      // ok a little messier ...
      int len = WritableUtils.decodeVIntSize(firstByte);
      if (len == 1) {
        fieldIdOut = firstByte;
      } else {
        long i = 0;
        for (int idx = 0; idx < len - 1; idx++) {
          byte b = in.readByte();
          i = i << 8;
          i = i | (b & 0xFF);
        }
        fieldIdOut = (int) (WritableUtils.isNegativeVInt(firstByte) ? (i ^ -1L)
            : i);
      }
    }

    if (fieldIdOut == -1) {
      // ok pop encoding mode off stack
      popFieldIdEncodingMode();
      // reduce nesting level ...
      _nestingLevel--;
    }
    return fieldIdOut;
  }

  // @Override
  public float readFloat(DataInput in) throws IOException {
    return in.readFloat();
  }

  // @Override
  public int readInt(DataInput in) throws IOException {
    return in.readInt();
  }

  // @Override
  public long readLong(DataInput in) throws IOException {
    return in.readLong();
  }

  // @Override
  public void readTextBytes(DataInput in, TextBytes stringBytes)
      throws IOException {
    if (_currentMode == FIELD_ID_ENCODING_MODE_SHORT) {
      // old encoding style
      int utfLen = in.readUnsignedShort();
      // ok set count in underlying object
      stringBytes.setLength(utfLen);
      // now if length != 0
      if (utfLen != 0) {
        // access the underlying buffer object
        FlexBuffer buffer = stringBytes.getBuffer();
        // make sure copy on write status
        buffer.copyOnWrite();
        // ok read in buytes
        in.readFully(buffer.get(), buffer.getOffset(), utfLen);
      }
    }
    // ok read in new way
    else {
      stringBytes.readFields(in);
    }
  }

  // @Override
  public void writeBool(DataOutput out, boolean b) throws IOException {
    out.writeBoolean(b);
  }

  // @Override
  public void writeFlexBuffer(DataOutput out, FlexBuffer buf)
      throws IOException {
    out.writeInt(buf.getCount());
    if (buf.getCount() != 0) {
      out.write(buf.get(), buf.getOffset(), buf.getCount());
    }
  }

  // @Override
  public void writeByte(DataOutput out, byte b) throws IOException {
    out.writeByte(b);
  }

  // @Override
  public void writeDouble(DataOutput out, double d) throws IOException {
    out.writeDouble(d);
  }

  // @Override
  public void writeFloat(DataOutput out, float f) throws IOException {
    out.writeFloat(f);
  }

  // @Override
  public void writeInt(DataOutput out, int i) throws IOException {
    out.writeInt(i);
  }

  // @Override
  public void writeLong(DataOutput out, long l) throws IOException {
    out.writeLong(l);
  }

  // @Override
  public void writeTextBytes(DataOutput out, TextBytes s) throws IOException {
    if (_currentMode == FIELD_ID_ENCODING_MODE_SHORT) {
      if (s.getLength() > 65535) {
        throw new IOException(
            "String Length Exceeds Max Encoding Length of 65535");
      } else {
        // encode the old fashioned way ...
        out.writeShort(s.getLength());
        if (s.getLength() != 0) {
          // and the bytes
          out.write(s.getBytes(), s.getOffset(), s.getLength());
        }
      }
    } else {
      // do it the new way
      s.write(out);
    }
  }

  public int readVInt(DataInput in) throws IOException {
    return WritableUtils.readVInt(in);
  }

  public long readVLong(DataInput in) throws IOException {
    return WritableUtils.readVLong(in);
  }

  public void writeVInt(DataOutput out, int i) throws IOException {
    WritableUtils.writeVInt(out, i);
  }

  public void writeVLong(DataOutput out, long l) throws IOException {
    WritableUtils.writeVLong(out, l);
  }
}
TOP

Related Classes of org.commoncrawl.rpc.BinaryProtocol

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.