org.apache.flink.runtime.state.gemini.engine.fs.GeminiDataInputStream Maven / Gradle / Ivy
/*
* 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.flink.runtime.state.gemini.engine.fs;
import org.apache.flink.core.fs.FSDataInputStream;
import org.apache.flink.util.Preconditions;
import javax.annotation.Nonnull;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.nio.ByteBuffer;
/**
* We use the implementation of {@link DataInputStream} currently,
* but we may optimize something later.
*/
public class GeminiDataInputStream extends FSDataInputStream implements DataInput {
protected final GeminiInputStream in;
/**
* Creates a DataInputStream that uses the specified
* underlying InputStream.
*
* @param in the specified input stream
*/
public GeminiDataInputStream(GeminiInputStream in) {
this.in = Preconditions.checkNotNull(in);
}
/**
* working arrays initialized on demand by readUTF.
*/
private byte[] bytearr = new byte[80];
private char[] chararr = new char[80];
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an int
in the range
* 0
to 255
. If no byte is available
* because the end of the stream has been reached, the value
* -1
is returned. This method blocks until input data
* is available, the end of the stream is detected, or an exception
* is thrown.
*
* This method
* simply performs in.read()
and returns the result.
*
* @return the next byte of data, or -1
if the end of the
* stream is reached.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public int read() throws IOException {
return in.read();
}
/**
* Reads some number of bytes from the contained input stream and
* stores them into the buffer array b
. The number of
* bytes actually read is returned as an integer. This method blocks
* until input data is available, end of file is detected, or an
* exception is thrown.
*
*
If b
is null, a NullPointerException
is
* thrown. If the length of b
is zero, then no bytes are
* read and 0
is returned; otherwise, there is an attempt
* to read at least one byte. If no byte is available because the
* stream is at end of file, the value -1
is returned;
* otherwise, at least one byte is read and stored into b
.
*
*
The first byte read is stored into element b[0]
, the
* next one into b[1]
, and so on. The number of bytes read
* is, at most, equal to the length of b
. Let k
* be the number of bytes actually read; these bytes will be stored in
* elements b[0]
through b[k-1]
, leaving
* elements b[k]
through b[b.length-1]
* unaffected.
*
*
The read(b)
method has the same effect as:
*
* read(b, 0, b.length)
*
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
* -1
if there is no more data because the end
* of the stream has been reached.
* @throws IOException if the first byte cannot be read for any reason
* other than end of file, the stream has been closed and the underlying
* input stream does not support reading after close, or another I/O
* error occurs.
* @see java.io.FilterInputStream#in
* @see java.io.InputStream#read(byte[], int, int)
*/
@Override
public final int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
/**
* Reads up to len
bytes of data from the contained
* input stream into an array of bytes. An attempt is made to read
* as many as len
bytes, but a smaller number may be read,
* possibly zero. The number of bytes actually read is returned as an
* integer.
*
* This method blocks until input data is available, end of file is
* detected, or an exception is thrown.
*
*
If len
is zero, then no bytes are read and
* 0
is returned; otherwise, there is an attempt to read at
* least one byte. If no byte is available because the stream is at end of
* file, the value -1
is returned; otherwise, at least one
* byte is read and stored into b
.
*
*
The first byte read is stored into element b[off]
, the
* next one into b[off+1]
, and so on. The number of bytes read
* is, at most, equal to len
. Let k be the number of
* bytes actually read; these bytes will be stored in elements
* b[off]
through b[off+
k-1]
,
* leaving elements b[off+
k]
through
* b[off+len-1]
unaffected.
*
*
In every case, elements b[0]
through
* b[off]
and elements b[off+len]
through
* b[b.length-1]
are unaffected.
*
* @param b the buffer into which the data is read.
* @param off the start offset in the destination array b
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
* -1
if there is no more data because the end
* of the stream has been reached.
* @throws NullPointerException If b
is null
.
* @throws IndexOutOfBoundsException If off
is negative,
* len
is negative, or len
is greater than
* b.length - off
* @throws IOException if the first byte cannot be read for any reason
* other than end of file, the stream has been closed and the underlying
* input stream does not support reading after close, or another I/O
* error occurs.
* @see java.io.FilterInputStream#in
* @see java.io.InputStream#read(byte[], int, int)
*/
@Override
public final int read(byte[] b, int off, int len) throws IOException {
readFully(b, off, len);
return len;
}
@Deprecated
public int read(int position, @Nonnull byte[] buffer, int offset, int length) throws IOException {
int n = 0;
while (n < length) {
int count = in.read(position + n, buffer, offset + n, length - n);
if (count < 0) {
throw new EOFException();
}
n += count;
}
return length;
}
public int readByteBuffer(int position, @Nonnull ByteBuffer buffer, int offset, int length) throws IOException {
in.readByteBuffer(position, buffer, offset, length);
if (length != buffer.position()) {
throw new EOFException("wanted length=" + length + " ;actual:" + buffer.getClass().getName() + " position=" + buffer.position() + " ;bufferLimist=" + buffer.limit() + ";bufferCap=" + buffer.capacity());
}
return length;
}
@Override
public void seek(long desired) throws IOException {
in.seek(desired);
}
@Override
public long getPos() throws IOException {
return in.getPos();
}
@Override
public void close() throws IOException {
in.close();
}
@Override
public int available() throws IOException {
return in.available();
}
@Override
public long skip(final long n) throws IOException {
return in.skip(n);
}
/**
* See the general contract of the readFully
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @param b the buffer into which the data is read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final void readFully(byte[] b) throws IOException {
readFully(b, 0, b.length);
}
/**
* See the general contract of the readFully
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the number of bytes to read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final void readFully(byte[] b, int off, int len) throws IOException {
if (len < 0) {
throw new IndexOutOfBoundsException();
}
int n = 0;
while (n < len) {
int count = in.read(b, off + n, len - n);
if (count < 0) {
throw new EOFException();
}
n += count;
}
}
/**
* See the general contract of the skipBytes
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @throws IOException if the contained input stream does not support
* seek, or the stream has been closed and
* the contained input stream does not support
* reading after close, or another I/O error occurs.
*/
@Override
public final int skipBytes(int n) throws IOException {
int total = 0;
int cur = 0;
while ((total < n) && ((cur = (int) in.skip(n - total)) > 0)) {
total += cur;
}
return total;
}
/**
* See the general contract of the readBoolean
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the boolean
value read.
* @throws EOFException if this input stream has reached the end.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final boolean readBoolean() throws IOException {
int ch = in.read();
if (ch < 0) {
throw new EOFException();
}
return (ch != 0);
}
/**
* See the general contract of the readByte
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next byte of this input stream as a signed 8-bit
* byte
.
* @throws EOFException if this input stream has reached the end.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final byte readByte() throws IOException {
int ch = in.read();
if (ch < 0) {
throw new EOFException();
}
return (byte) (ch);
}
/**
* See the general contract of the readUnsignedByte
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next byte of this input stream, interpreted as an
* unsigned 8-bit number.
* @throws EOFException if this input stream has reached the end.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final int readUnsignedByte() throws IOException {
int ch = in.read();
if (ch < 0) {
throw new EOFException();
}
return ch;
}
/**
* See the general contract of the readShort
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next two bytes of this input stream, interpreted as a
* signed 16-bit number.
* @throws EOFException if this input stream reaches the end before
* reading two bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final short readShort() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
return (short) ((ch1 << 8) + (ch2 << 0));
}
/**
* See the general contract of the readUnsignedShort
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next two bytes of this input stream, interpreted as an
* unsigned 16-bit integer.
* @throws EOFException if this input stream reaches the end before
* reading two bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final int readUnsignedShort() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
return (ch1 << 8) + (ch2 << 0);
}
/**
* See the general contract of the readChar
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next two bytes of this input stream, interpreted as a
* char
.
* @throws EOFException if this input stream reaches the end before
* reading two bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final char readChar() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
return (char) ((ch1 << 8) + (ch2 << 0));
}
/**
* See the general contract of the readInt
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next four bytes of this input stream, interpreted as an
* int
.
* @throws EOFException if this input stream reaches the end before
* reading four bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) {
throw new EOFException();
}
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
private byte[] readBuffer = new byte[8];
/**
* See the general contract of the readLong
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next eight bytes of this input stream, interpreted as a
* long
.
* @throws EOFException if this input stream reaches the end before
* reading eight bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.FilterInputStream#in
*/
@Override
public final long readLong() throws IOException {
readFully(readBuffer, 0, 8);
return (((long) readBuffer[0] << 56) + ((long) (readBuffer[1] & 255) << 48) + ((long) (readBuffer[2] & 255) << 40) + ((long) (readBuffer[3] & 255) << 32) + ((long) (readBuffer[4] & 255) << 24) + ((readBuffer[5] & 255) << 16) + ((readBuffer[6] & 255) << 8) + ((readBuffer[7] & 255) << 0));
}
/**
* See the general contract of the readFloat
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next four bytes of this input stream, interpreted as a
* float
.
* @throws EOFException if this input stream reaches the end before
* reading four bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.DataInputStream#readInt()
* @see java.lang.Float#intBitsToFloat(int)
*/
@Override
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
/**
* See the general contract of the readDouble
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next eight bytes of this input stream, interpreted as a
* double
.
* @throws EOFException if this input stream reaches the end before
* reading eight bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @see java.io.DataInputStream#readLong()
* @see java.lang.Double#longBitsToDouble(long)
*/
@Override
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
/**
* See the general contract of the readLine
* method of DataInput
.
*
*
Bytes for this operation are read from the contained
* input stream.
*
* @return the next line of text from this input stream.
* @throws IOException if an I/O error occurs.
* @see java.io.BufferedReader#readLine()
* @see java.io.FilterInputStream#in
* @deprecated This method does not properly convert bytes to characters.
* As of JDK 1.1, the preferred way to read lines of text is via the
* BufferedReader.readLine()
method. Programs that use the
* DataInputStream
class to read lines can be converted to use
* the BufferedReader
class by replacing code of the form:
*
* DataInputStream d = new DataInputStream(in);
*
* with:
*
* BufferedReader d
* = new BufferedReader(new InputStreamReader(in));
*
*/
@Deprecated
@Override
public final String readLine() throws IOException {
throw new UnsupportedOperationException();
}
/**
* See the general contract of the readUTF
* method of DataInput
.
*
* Bytes for this operation are read from the contained
* input stream.
*
* @return a Unicode string.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @throws UTFDataFormatException if the bytes do not represent a valid
* modified UTF-8 encoding of a string.
* @see java.io.DataInputStream#readUTF(java.io.DataInput)
*/
@Override
public final String readUTF() throws IOException {
return readUTF(this);
}
/**
* Reads from the
* stream in
a representation
* of a Unicode character string encoded in
* modified UTF-8 format;
* this string of characters is then returned as a String
.
* The details of the modified UTF-8 representation
* are exactly the same as for the readUTF
* method of DataInput
.
*
* @param in a data input stream.
* @return a Unicode string.
* @throws EOFException if the input stream reaches the end
* before all the bytes.
* @throws IOException the stream has been closed and the contained
* input stream does not support reading after close, or
* another I/O error occurs.
* @throws UTFDataFormatException if the bytes do not represent a
* valid modified UTF-8 encoding of a Unicode string.
* @see java.io.DataInputStream#readUnsignedShort()
*/
public static final String readUTF(DataInput in) throws IOException {
int utflen = in.readUnsignedShort();
byte[] bytearr = null;
char[] chararr = null;
if (in instanceof GeminiDataInputStream) {
GeminiDataInputStream dis = (GeminiDataInputStream) in;
if (dis.bytearr.length < utflen) {
dis.bytearr = new byte[utflen * 2];
dis.chararr = new char[utflen * 2];
}
chararr = dis.chararr;
bytearr = dis.bytearr;
} else {
bytearr = new byte[utflen];
chararr = new char[utflen];
}
int c, char2, char3;
int count = 0;
int chararrCount = 0;
in.readFully(bytearr, 0, utflen);
while (count < utflen) {
c = (int) bytearr[count] & 0xff;
if (c > 127) {
break;
}
count++;
chararr[chararrCount++] = (char) c;
}
while (count < utflen) {
c = (int) bytearr[count] & 0xff;
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
/* 0xxxxxxx*/
count++;
chararr[chararrCount++] = (char) c;
break;
case 12:
case 13:
/* 110x xxxx 10xx xxxx*/
count += 2;
if (count > utflen) {
throw new UTFDataFormatException("malformed input: partial character at end");
}
char2 = (int) bytearr[count - 1];
if ((char2 & 0xC0) != 0x80) {
throw new UTFDataFormatException("malformed input around byte " + count);
}
chararr[chararrCount++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
count += 3;
if (count > utflen) {
throw new UTFDataFormatException("malformed input: partial character at end");
}
char2 = (int) bytearr[count - 2];
char3 = (int) bytearr[count - 1];
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException("malformed input around byte " + (count - 1));
}
chararr[chararrCount++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw new UTFDataFormatException("malformed input around byte " + count);
}
}
// The number of chars produced may be less than utflen
return new String(chararr, 0, chararrCount);
}
}