blob: 84cbdeb7681612be3ad3d7c489c980e377794d00 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.giraph.utils;
import java.io.IOException;
import java.lang.reflect.Field;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_BOOLEAN;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_BYTE;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_CHAR;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_SHORT;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_INT;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_LONG;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_FLOAT;
import static org.apache.giraph.utils.ByteUtils.SIZE_OF_DOUBLE;
/**
* Byte array input stream that uses Unsafe methods to deserialize
* much faster
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
"RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
public class UnsafeArrayReads extends UnsafeReads {
/** Access to the unsafe class */
private static final sun.misc.Unsafe UNSAFE;
static {
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
UNSAFE = (sun.misc.Unsafe) field.get(null);
// Checkstyle exception due to needing to check if unsafe is allowed
// CHECKSTYLE: stop IllegalCatch
} catch (Exception e) {
// CHECKSTYLE: resume IllegalCatch
throw new RuntimeException("UnsafeArrayReads: Failed to " +
"get unsafe", e);
}
}
/** Offset of a byte array */
private static final long BYTE_ARRAY_OFFSET =
UNSAFE.arrayBaseOffset(byte[].class);
/**
* Constructor
*
* @param buf Buffer to read from
*/
public UnsafeArrayReads(byte[] buf) {
super(buf.length);
this.buffer = buf;
}
/**
* Constructor.
*
* @param buf Buffer to read from
* @param offset Offsetin the buffer to start reading from
* @param length Max length of the buffer to read
*/
public UnsafeArrayReads(byte[] buf, int offset, int length) {
super(offset, length);
this.buffer = buf;
}
@Override
public int available() {
return (int) (limit - position);
}
@Override
public boolean endOfInput() {
return available() == 0;
}
@Override
public int getPos() {
return (int) position;
}
@Override
public void readFully(byte[] b) throws IOException {
require(b.length);
System.arraycopy(buffer, (int) position, b, 0, b.length);
position += b.length;
}
@Override
public void readFully(byte[] b, int off, int len) throws IOException {
require(len);
System.arraycopy(buffer, (int) position, b, off, len);
position += len;
}
@Override
public boolean readBoolean() {
require(SIZE_OF_BOOLEAN);
boolean value = UNSAFE.getBoolean(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_BOOLEAN;
return value;
}
@Override
public byte readByte() {
require(SIZE_OF_BYTE);
byte value = UNSAFE.getByte(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_BYTE;
return value;
}
@Override
public int readUnsignedByte() throws IOException {
return (short) (readByte() & 0xFF);
}
@Override
public short readShort() {
require(SIZE_OF_SHORT);
short value = UNSAFE.getShort(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_SHORT;
return value;
}
@Override
public int readUnsignedShort() throws IOException {
return readShort() & 0xFFFF;
}
@Override
public char readChar() {
require(SIZE_OF_CHAR);
char value = UNSAFE.getChar(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_CHAR;
return value;
}
@Override
public int readInt() {
require(SIZE_OF_INT);
int value = UNSAFE.getInt(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_INT;
return value;
}
@Override
public long readLong() {
require(SIZE_OF_LONG);
long value = UNSAFE.getLong(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_LONG;
return value;
}
@Override
public float readFloat() {
require(SIZE_OF_FLOAT);
float value = UNSAFE.getFloat(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_FLOAT;
return value;
}
@Override
public double readDouble() {
require(SIZE_OF_DOUBLE);
double value = UNSAFE.getDouble(buffer,
BYTE_ARRAY_OFFSET + position);
position += SIZE_OF_DOUBLE;
return value;
}
/**
* Get an int at an arbitrary position in a byte[]
*
* @param buf Buffer to get the int from
* @param pos Position in the buffer to get the int from
* @return Int at the buffer position
*/
public static int getInt(byte[] buf, int pos) {
return UNSAFE.getInt(buf,
BYTE_ARRAY_OFFSET + pos);
}
}