/* * 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.ignite.internal.processors.hadoop.shuffle.direct; import org.apache.ignite.internal.util.GridUnsafe; import org.jetbrains.annotations.NotNull; import java.io.DataOutput; import java.io.IOException; import java.io.OutputStream; import java.io.UTFDataFormatException; import java.nio.charset.StandardCharsets; import static org.apache.ignite.internal.util.GridUnsafe.BYTE_ARR_OFF; /** * Hadoop data output for direct communication. */ public class HadoopDirectDataOutput extends OutputStream implements DataOutput { /** Flush size. */ private final int flushSize; /** Data buffer. */ private byte[] buf; /** Buffer size. */ private int bufSize; /** Position. */ private int pos; /** * Constructor. * * @param flushSize Flush size. */ public HadoopDirectDataOutput(int flushSize) { this(flushSize, flushSize); } /** * Constructor. * * @param flushSize Flush size. * @param allocSize Allocation size. */ public HadoopDirectDataOutput(int flushSize, int allocSize) { this.flushSize = flushSize; buf = new byte[allocSize]; bufSize = allocSize; } /** {@inheritDoc} */ @Override public void write(@NotNull byte[] b) throws IOException { write(b, 0, b.length); } /** {@inheritDoc} */ @Override public void write(@NotNull byte[] b, int off, int len) throws IOException { int writePos = ensure(len); System.arraycopy(b, off, buf, writePos, len); } /** {@inheritDoc} */ @Override public void write(int val) throws IOException { writeByte(val); } /** {@inheritDoc} */ @Override public void writeBoolean(boolean val) throws IOException { writeByte(val ? (byte)1 : (byte)0); } /** {@inheritDoc} */ @Override public void writeByte(int val) throws IOException { int writePos = ensure(1); buf[writePos] = (byte)val; } /** {@inheritDoc} */ @Override public void writeShort(int val) throws IOException { int writePos = ensure(2); GridUnsafe.putShort(buf, BYTE_ARR_OFF + writePos, (short)val); } /** {@inheritDoc} */ @Override public void writeChar(int val) throws IOException { int writePos = ensure(2); GridUnsafe.putChar(buf, BYTE_ARR_OFF + writePos, (char)val); } /** {@inheritDoc} */ @Override public void writeInt(int val) throws IOException { int writePos = ensure(4); GridUnsafe.putInt(buf, BYTE_ARR_OFF + writePos, val); } /** {@inheritDoc} */ @Override public void writeLong(long val) throws IOException { int writePos = ensure(8); GridUnsafe.putLong(buf, BYTE_ARR_OFF + writePos, val); } /** {@inheritDoc} */ @Override public void writeFloat(float val) throws IOException { int writePos = ensure(4); GridUnsafe.putFloat(buf, BYTE_ARR_OFF + writePos, val); } /** {@inheritDoc} */ @Override public void writeDouble(double val) throws IOException { int writePos = ensure(8); GridUnsafe.putDouble(buf, BYTE_ARR_OFF + writePos, val); } /** {@inheritDoc} */ @Override public void writeBytes(@NotNull String str) throws IOException { for(int i = 0; i < str.length(); ++i) write((byte)str.charAt(i)); } /** {@inheritDoc} */ @Override public void writeChars(@NotNull String str) throws IOException { for (int i = 0; i < str.length(); ++i) writeChar(str.charAt(i)); } /** {@inheritDoc} */ @Override public void writeUTF(@NotNull String str) throws IOException { byte[] bytes = str.getBytes(StandardCharsets.UTF_8); int len = bytes.length; if (len > 65535) throw new UTFDataFormatException("UTF8 form of string is longer than 65535 bytes: " + str); writeShort((short)len); write(bytes); } /** * @return Buffer. */ public byte[] buffer() { return buf; } /** * @return Buffer length (how much memory is allocated). */ public int bufferLength() { return bufSize; } /** * @return Position. */ public int position() { return pos; } /** * @return Whether buffer is ready for flush. */ public boolean readyForFlush() { return pos >= flushSize; } /** * Reset the stream. */ public void reset() { pos = 0; } /** * Ensure that the given amount of bytes is available within the stream, then shift the position. * * @param cnt Count. * @return Position */ private int ensure(int cnt) { int pos0 = pos; if (pos0 + cnt > bufSize) grow(pos0 + cnt); pos += cnt; return pos0; } /** * Grow array up to the given count. * * @param cnt Count. */ private void grow(int cnt) { int bufSize0 = (int)(bufSize * 1.1); if (bufSize0 < cnt) bufSize0 = cnt; byte[] buf0 = new byte[bufSize0]; System.arraycopy(buf, 0, buf0, 0, pos); buf = buf0; bufSize = bufSize0; } }