data.intelligence.platform.yarn.etl.io.BytesRefWritable.java Source code

Java tutorial

Introduction

Here is the source code for data.intelligence.platform.yarn.etl.io.BytesRefWritable.java

Source

/**
 * 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 data.intelligence.platform.yarn.etl.io;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.io.WritableFactories;
import org.apache.hadoop.io.WritableFactory;

/**
 * <tt>BytesRefWritable</tt> referenced a section of byte array. It can be used
 * to avoid unnecessary byte copy.
 */
public class BytesRefWritable implements Writable, Comparable<BytesRefWritable> {

    private static final byte[] EMPTY_BYTES = new byte[0];
    public static BytesRefWritable ZeroBytesRefWritable = new BytesRefWritable();

    int start = 0;
    int length = 0;
    byte[] bytes = null;

    LazyDecompressionCallback lazyDecompressObj;

    /**
     * Create a zero-size bytes.
     */
    public BytesRefWritable() {
        this(EMPTY_BYTES);
    }

    /**
     * Create a BytesRefWritable with <tt>length</tt> bytes.
     */
    public BytesRefWritable(int length) {
        assert length > 0;
        this.length = length;
        bytes = new byte[this.length];
        start = 0;
    }

    /**
     * Create a BytesRefWritable referenced to the given bytes.
     */
    public BytesRefWritable(byte[] bytes) {
        this.bytes = bytes;
        length = bytes.length;
        start = 0;
    }

    /**
     * Create a BytesRefWritable referenced to one section of the given bytes.
     * The section is determined by argument <tt>offset</tt> and <tt>len</tt>.
     */
    public BytesRefWritable(byte[] data, int offset, int len) {
        bytes = data;
        start = offset;
        length = len;
    }

    /**
     * Create a BytesRefWritable referenced to one section of the given bytes.
     * The argument <tt>lazyDecompressData</tt> refers to a
     * LazyDecompressionCallback object. The arguments <tt>offset</tt> and
     * <tt>len</tt> are referred to uncompressed bytes of
     * <tt>lazyDecompressData</tt>. Use <tt>offset</tt> and <tt>len</tt> after
     * uncompressing the data.
     */
    public BytesRefWritable(LazyDecompressionCallback lazyDecompressData, int offset, int len) {
        lazyDecompressObj = lazyDecompressData;
        start = offset;
        length = len;
    }

    private void lazyDecompress() throws IOException {
        if (bytes == null && lazyDecompressObj != null) {
            bytes = lazyDecompressObj.decompress();
        }
    }

    /**
     * Returns a copy of the underlying bytes referenced by this instance.
     * 
     * @return a new copied byte array
     * @throws IOException
     */
    public byte[] getBytesCopy() throws IOException {
        lazyDecompress();
        byte[] bb = new byte[length];
        System.arraycopy(bytes, start, bb, 0, length);
        return bb;
    }

    /**
     * Returns the underlying bytes.
     * 
     * @throws IOException
     */
    public byte[] getData() throws IOException {
        lazyDecompress();
        return bytes;
    }

    /**
     * readFields() will corrupt the array. So use the set method whenever
     * possible.
     * 
     * @see #readFields(DataInput)
     */
    public void set(byte[] newData, int offset, int len) {
        bytes = newData;
        start = offset;
        length = len;
        lazyDecompressObj = null;
    }

    /**
     * readFields() will corrupt the array. So use the set method whenever
     * possible.
     * 
     * @see #readFields(DataInput)
     */
    public void set(LazyDecompressionCallback newData, int offset, int len) {
        bytes = null;
        start = offset;
        length = len;
        lazyDecompressObj = newData;
    }

    public void writeDataTo(DataOutput out) throws IOException {
        lazyDecompress();
        out.write(bytes, start, length);
    }

    /**
     * Always reuse the bytes array if length of bytes array is equal or greater
     * to the current record, otherwise create a new one. readFields will
     * corrupt the array. Please use set() whenever possible.
     * 
     * @see #set(byte[], int, int)
     */
    public void readFields(DataInput in) throws IOException {
        int len = in.readInt();
        if (len > bytes.length) {
            bytes = new byte[len];
        }
        start = 0;
        length = len;
        in.readFully(bytes, start, length);
    }

    /** {@inheritDoc} */
    public void write(DataOutput out) throws IOException {
        lazyDecompress();
        out.writeInt(length);
        out.write(bytes, start, length);
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        return super.hashCode();
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(3 * length);
        for (int idx = start; idx < length; idx++) {
            // if not the first, put a blank separator in
            if (idx != 0) {
                sb.append(' ');
            }
            String num = Integer.toHexString(0xff & bytes[idx]);
            // if it is only one digit, add a leading 0.
            if (num.length() < 2) {
                sb.append('0');
            }
            sb.append(num);
        }
        return sb.toString();
    }

    /** {@inheritDoc} */
    @Override
    public int compareTo(BytesRefWritable other) {
        if (other == null) {
            throw new IllegalArgumentException("Argument can not be null.");
        }
        if (this == other) {
            return 0;
        }
        try {
            return WritableComparator.compareBytes(getData(), start, getLength(), other.getData(), other.start,
                    other.getLength());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean equals(Object right_obj) {
        if (right_obj == null || !(right_obj instanceof BytesRefWritable)) {
            return false;
        }
        return compareTo((BytesRefWritable) right_obj) == 0;
    }

    static {
        WritableFactories.setFactory(BytesRefWritable.class, new WritableFactory() {

            @Override
            public Writable newInstance() {
                return new BytesRefWritable();
            }

        });
    }

    public int getLength() {
        return length;
    }

    public int getStart() {
        return start;
    }
}